以强类型的方式提取属性名称



以下答案介绍了如何从类型中安全地提取属性名。这个答案所实现的是,事实上,如果有一个错误的类型,你会得到一个编译时错误,而不是运行时错误:

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"

游乐场

最新更新