打字稿限制对象属性的计数

Posted

技术标签:

【中文标题】打字稿限制对象属性的计数【英文标题】:typescript restrict count of object's properties 【发布时间】:2017-01-04 12:49:53 【问题描述】:

是否可以限制对象属性的数量,比如说我想限制对象只有一个字符串属性(任何名称),我可以这样做:

[index: string]: any

限制属性的类型,但可以限制属性的数量吗?

【问题讨论】:

【参考方案1】:

很可能没有。我想到的最好的解决方案是用你的自定义类包装一个Object(或Map),方法是set(key: string, val: any)get(key: string),在某些情况下不允许向基础集合添加新项目。

【讨论】:

【参考方案2】:

因为this question已被标记为与此重复,所以让我在这里回答。

检查类型是否为联合

/**
 * @see https://***.com/questions/53953814/typescript-check-if-a-type-is-a-union/53955431
 */
type IsSingleton<T> =
  [T] extends [UnionToIntersection<T>]
    ? true
    : false

/**
 * @author https://***.com/users/2887218/jcalz
 * @see https://***.com/a/50375286/10325032
 */
type UnionToIntersection<Union> =
  (Union extends any
    ? (argument: Union) => void
    : never
  ) extends (argument: infer Intersection) => void
    ? Intersection
  : never;

只允许单例类型

type SingletonOnly<T> =
  IsSingleton<T> extends true
    ? T
    : never

限制函数只接受单例类型

declare function foo<K extends string>(s: SingletonOnly<K>): void

declare const singleton: 'foo';
foo(singleton);

declare const union: "foo" | "bar";
foo(union); // Compile-time error

TypeScript Playground

【讨论】:

【参考方案3】:

这个问题在 *** 上有很多答案(包括 this detailed one),但没有一个适合我的情况,这与此处发布的类似。

问题

我有一个接受对象的函数。如果传递的对象没有确切的一个键,我希望它抛出 Compilation Error (Typescript)。例如

f(); // Must error here, as it has less than one key!
f( x: 5 );
f( x: 5, y : 6 ); // Must error here, as it has more than one key!

解决方案

使用流行的UnionToIntersection和IsUnion,通过以下实用函数实现。

type SingleKey<T> = IsUnion<keyof T> extends true ? never :  extends T ? never : T;

完整代码:

// From https://***.com/a/50375286
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

// From: https://***.com/a/53955431
type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;

// Here we come!
type SingleKey<T> = IsUnion<keyof T> extends true ? never :  extends T ? never : T;

// Usage:
function f<T extends Record<string, any>>(obj: SingleKey<T>) 
    console.log( obj );


f(); // errors here!
f( x: 5 );
f( x: 5, y : 6 ); // errors here!

Playground Link

【讨论】:

Broken Playground 链接,您现在可以找到它here 感谢@Stanislas。更新了链接

以上是关于打字稿限制对象属性的计数的主要内容,如果未能解决你的问题,请参考以下文章

如何将方法的泛型类型限制为打字稿中的对象?

打字稿,将键限制为数组元素

如何覆盖打字稿中的属性?

打字稿条件类型内部类型

基于嵌套对象内属性的打字稿联合

打字稿检查对象中的属性是不是以类型安全的方式