以下答案介绍了如何从类型中安全地提取属性名。这个答案所实现的是,事实上,如果有一个错误的类型,你会得到一个编译时错误,而不是运行时错误:
https://stackoverflow.com/a/42516869/274677
但是,以这种方式提取的属性名称被键入为string
,而不是字符串文字(具有实际属性的名称(。这具有一些限制性含义,例如,它不允许它们与Omit
实用程序类型一起使用。
这个打字游戏场链接说明了这个问题。为了完整起见,粘贴在下面的游乐场代码:
function propertyOf<T>(name: keyof T) {
return name;
}
type AB = {a: number, b: number};
const A = propertyOf<AB>('a');
/*
* Now say that I want to constuct the following type:
*
* type B = {b: number}
*
* ... with the qualification that I want to construct it by omitting
* some properties from a wider type. `A` cannot be used for this
* purpose so one has to again type the name of the property as: 'a'
*
*/
type B_by_omit = Omit<AB, 'a'> // type of B_by_omit is correctly pronounced as {b: number}
type B_by_omit2 = Omit<AB, typeof A> // type of B_by_omit2 is {}
有没有办法安全地从类型中提取属性名称,并将其键入为字符串文字?
如果您希望propertyOf
在向其传递"a"
时返回字符串文字类型"a"
,我们将需要向函数添加另一个泛型类型K
,该类型将由参数name
推断。
// this does not work. see below
function propertyOf<T, K extends keyof T>(name: K): K {
return name;
}
但这是不起作用的。问题是TypeScript还不支持部分类型推理。因此,在自动推断K
的同时,我们不能显式地为T
提供类型。
为了达到类似的效果,我们可以用咖喱代替。
function propertyOf<T>() {
return <K extends keyof T>(name: K) => name;
}
该函数现在的调用方式如下:
const A = propertyOf<AB>()("a");
// ^? const A: "a"
游乐场