我有一个用于映射可迭代值的函数,与Array.prototype.map()
非常相似,但是由于示例中的这些细节无关紧要,因此本示例将其简化为基本等效:
function select <T, U> (array: T[], selectFn: (value: T, index: number, array: T[]) => U, thisArg?: unknown): U[] {
return array.map(selectKeyOrFn, thisArg);
}
select(['foo', 'bar'], s => s.length);
到目前为止,太好了。一切都会编译。现在,我想接受一个函数或第二个参数的keyof T
。我不确定如何最好地为此过载签名定义类型参数,但这是我失败的方法:
type KeyOfValue<T, U extends T[keyof T]> = U extends T[infer K] ? K : never;
function select <T, U extends T[keyof T]> (array: T[], selectKey: KeyOfValue<T, U>): U[]
function select <T, U> (array: T[], selectFn: (value: T, index: number, array: T[]) => U, thisArg?: unknown): U[]
function select <T, U> (array: T[], selectKeyOrFn: (U extends T[keyof T] ? KeyOfValue<T, U> : never) | ((value: T, index: number, array: T[]) => U), thisArg?: unknown): U[] {
return typeof selectKeyOrFn === 'function'
? array.map(selectKeyOrFn, thisArg)
: array.map(value => value[selectKeyOrFn]);
}
select(['foo', 'bar'], 'length');
select(['foo', 'bar'], s => s.length);
主要问题似乎是我的KeyOfValue
类型不允许我尝试将infer K
用作索引T
的语法:
类型“ K”不能用于索引类型“ T”。
如何成功原型化此重载函数?我不希望求助于KeyOfValue
之类的帮助程序类型,但目前我想不出解决办法。
答案 0 :(得分:1)
我认为您在这里使条件类型变得过于复杂。为键设置类型参数并使用类型查询会更好。同样,对于实现签名,您可以合并两个重载签名,而不必使用相同的book
作为返回类型:
U