typescript限制对象属性的数量

时间:2016-08-28 10:06:13

标签: typescript

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

{[index: string]: any}

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

3 个答案:

答案 0 :(得分:3)

很可能没有。我想到的最佳解决方案是将Object(或Map)与自定义类包装在一起,方法set(key: string, val: any)get(key: string)可以禁止向底层添加新项目在某些情况下收集。

答案 1 :(得分:3)

关于Stackoverflow的这个问题有很多答案(包括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!

解决方案

我使用流行的UnionToIntersectionIsUnion通过以下实用程序功能实现了这一目标。

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

完整代码:

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

// From: https://stackoverflow.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

答案 2 :(得分:0)

由于this question已被标记为与此副本的副本,因此我在这里回答。

检查类型是否为联合

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

/**
 * @author https://stackoverflow.com/users/2887218/jcalz
 * @see https://stackoverflow.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