查看此 URL https://www.typescriptlang.org/docs/handbook/advanced-types.html上的 Typescript 文档
type FunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
有人可以向我解释一下右括号后的 [keyof T] 是什么意思吗?这种语法有任何文档吗?
查看此 URL https://www.typescriptlang.org/docs/handbook/advanced-types.html上的 Typescript 文档
type FunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
有人可以向我解释一下右括号后的 [keyof T] 是什么意思吗?这种语法有任何文档吗?
这就是所谓的“查找类型”。
keyof X
返回一个类型的所有键
如果
interface a {
foo: never
bar: string
baz: number
}
那么type not_here = a['foo']
将是never
但是查找类型也支持传入keyof Something
,所以
a[keyof a]
将是所有类型的a
s 键/属性的联合,即never | string | number
. 虽然never
那里没有任何意义,所以 TS 会自动忽略它,导致string | number
.
(当然可以a[keyof b]
,这里没有限制)
我发现找出像这样的复杂类型的最佳方法是像我在这里所做的那样按步骤分解它们:
interface test {
a: string
b: () => void
c: () => void
}
type T_A<T> = {
[K in keyof T]: T[K]
};
type T_B<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
};
type T_C<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
type a = T_A<test>
type b = T_B<test>
type c = T_C<test>
有了这个,您可以看到为获得所需结果所采取的各个步骤,即“函数类型的键的联合”。
keyof T
表示该T
类型的有效键(您可能知道这一点)。当您拥有[x]
接口或联合类型时,它会选择名称为 的属性/成员的类型x
。例如(游乐场链接):
interface Example {
a: number;
b: string;
}
type E1 = Example["a"];
/*
type E1 = number;
*/
据我所知,这些“查找类型”仅记录在此处的 TypeScript 2.1 发行说明中:
keyof
和查找类型 在 JavaScript 中,将属性名称作为参数的 API 相当普遍,但到目前为止,还无法表达这些 API 中出现的类型关系。输入索引类型查询或
keyof
;索引类型查询keyof T
产生 T 允许的属性名称的类型。keyof T
类型被认为是字符串的子类型。例子
interface Person { name: string; age: number; location: string; } type K1 = keyof Person; // "name" | "age" | "location" type K2 = keyof Person[]; // "length" | "push" | "pop" | "concat" | ... type K3 = keyof { [x: string]: Person }; // string
其双重属性是索引访问类型,也称为查找类型。从语法上讲,它们看起来与元素访问完全一样,但写成类型:
例子
type P1 = Person["name"]; // string type P2 = Person["name" | "age"]; // string | number type P3 = string["charAt"]; // (pos: number) => string type P4 = string[]["push"]; // (...items: string[]) => number type P5 = string[][0]; // string
您可以将此模式与类型系统的其他部分一起使用,以获取类型安全的查找。
function getProperty<T, K extends keyof T>(obj: T, key: K) { return obj[key]; // Inferred type is T[K] } function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) { obj[key] = value; } let x = { foo: 10, bar: "hello!" }; let foo = getProperty(x, "foo"); // number let bar = getProperty(x, "bar"); // string let oops = getProperty(x, "wargarbl"); // Error! "wargarbl" is not "foo" | "bar" setProperty(x, "foo", "string"); // Error!, string expected number
的主要部分为所有非函数类型的属性FunctionPropertyNames<T>
生成一个带有never
类型成员的接口T
,并为那些是原始成员类型生成一个接口。例如,如示例中所示,如果您这样做:
interface Part {
id: number;
name: string;
subparts: Part[];
updatePart(newName: string): void;
}
type T1 = FunctionPropertyNames<Part>;
T1
最终是"updatePart"
因为这是T
( Part
) 中唯一具有函数类型的键。如果没有该[keyof T]
部分,您将获得与never
成员的界面(游乐场链接):
type FunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
type Example<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}/* Same as above, but without [keyof T] here*/;
interface Part {
id: number;
name: string;
subparts: Part[];
updatePart(newName: string): void;
}
type T1 = FunctionPropertyNames<Part>;
/*
type T1 = "updatePart"
*/
type E1 = Example<Part>;
/*
type E1 = {
id: never;
name: never;
subparts: never;
updatePart: "updatePart";
}
*/
它是提供函数类型属性名称[keyof T]
的部分,而不是函数类型属性本身(和类型属性)。FunctionPropertyNames
never
这个 [keyof T] 表示 T 中的任何属性。
为了更好地理解,请采取以下措施:
type AB = {
aa: number,
ab: () => number,
cd: () => number,
ef: () => number
}
type FunctionPropertyKeyToNames<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}
/* The only possible value for this example will be { aa: never, ab: 'ab', cd: 'cd', ef: 'ef' } */
const example: FunctionPropertyKeyToNames<AB> =
现在,使用 [keyof T] 我们只会得到值,
理论上never, 'ab', 'cd', 'ef'
,但由于 Typescript 不会never
为你解析为值你
最终只会得到'ab', 'cd', 'ef'