Typescript:如何将类型的属性过滤为特定类型的属性?

Lab*_*wal 16 typescript

我有一个界面

export interface MyInterface {
    a: number;
    b: string;
    c: number;
}
Run Code Online (Sandbox Code Playgroud)

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

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

type MyType = keyof MyInterface // gives 'a'|'b'|'c'
Run Code Online (Sandbox Code Playgroud)

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

jca*_*alz 30

你当然可以在 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"
Run Code Online (Sandbox Code Playgroud)

在此,返回其属性可分配给 的KeysMatching<T, V>键集。它使用条件映射类型以及属性查找。对于中的每个键,它检查是否可分配给。如果是,则返回密钥;如果不是,则返回。所以对于你的类型来说,它会像. 然后我们查找属性值并获得类型的并集,例如它减少到,正如您想要的那样。TVKkeyof TT[K]VKnever{a: "a", b: never, c: "c"}"a" | never | "c""a" | "c"

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

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

type AnotherType = KeysMatching<AnotherInterface, number>;
// type AnotherType = "narrower" | "exact"
Run Code Online (Sandbox Code Playgroud)

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"
Run Code Online (Sandbox Code Playgroud)

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

链接到代码