从按值类型过滤的接口键创建文字类型

时间:2019-07-03 06:06:37

标签: typescript

我有一个界面

export interface MyInterface {
    a: number;
    b: string;
    c: number;
}

我想创建属性名称的文字类型,其值的类型为数字

我知道如何使用所有属性名称获取类型

type MyType = keyof MyInterface // gives 'a'|'b'|'c'

我只想得到'a'|'c'

2 个答案:

答案 0 :(得分:1)

您当然可以在TypeScript中定义这样的类型:

type KeysMatching<T extends object, V> = {
  [K in keyof T]-?: T[K] extends V ? K : never
}[keyof T];

type MyType = KeysMatching<MyInterface, number>;
// type MyType = "a" | "c"

在此,KeysMatching<T, V>返回属性T可分配给V的一组键。它使用conditionalmapped类型以及属性lookup。对于K中的每个键keyof T,它检查T[K]是否可分配给V。如果是这样,它将返回键K;如果不是,则返回never。因此,对于您的类型,它类似于{a: "a", b: never, c: "c"}。然后,我们查询属性值,并获得"a" | never | "c"之类的类型的并集,该类型会完全按照您的需要缩减为"a" | "c"

请注意,读取属性时,KeysMatching<T, V>仅返回其值与V匹配的属性键。完全是VV子类型的那些

interface AnotherInterface {
  narrower: 1;
  exact: number;
  wider: string | number;
}

type AnotherType = KeysMatching<AnotherInterface, number>;
// type AnotherType = "narrower" | "exact"

如果您想在写入 V的属性时获取与T匹配的键...正好是V V,那么您需要使用KeysMatching的其他实现:

type KeysMatchingWrite<T extends object, V> = {
  [K in keyof T]-?: [V] extends [T[K]] ? K : never
}[keyof T];

type AnotherTypeWrite = KeysMatchingWrite<AnotherInterface, number>;
// type AnotherTypeWrite = "exact" | "wider"

无论如何,希望能有所帮助。祝你好运!

Link to code

答案 1 :(得分:0)

不要以为您可以按类型选择属性,但是如果您知道接受的属性,则可以基于这样的属性创建一个新类型;

type MyType = Pick<MyInterface, 'a' | 'c'>

我喜欢this blog post,它涵盖了大多数类型(ReadonlyPartialRequiredPickRecord,{{1 }},Extract等),但我知道Exclude也是最近引入的。

我发现这个答案可以更好地解释它; Exclude property from type