从高层次来看,我试图定义一个通用类型,接受两种类型:
- T -类型
- V -使用T 键访问T时返回的值类型
允许一个并集
- 任何返回V类型的T类型键
- 一个接受T类型实例并返回V类型值的函数
为此,我定义了以下内容:
type KeysWithValueOfType<T, V> = {
[K in keyof T]-?: Exclude<T[K], undefined | null> extends V ? K : never
}[keyof T]
从这里取来的
https://stackoverflow.com/a/54520829/50776
然后定义一个选择器类型,它是键和函数访问器的联合:
type Selector<T, V> = KeysWithValueOfType<T, V> | ((t: T) => V)
在这一点上,我想当尝试创建一个泛型函数来解析给定类型T的实例的值的访问器时
function getValue<Data extends Aggregate, Result>(
selector: Selector<Data, Result>,
data: Data
): Result {
// If a function, evaluate, otherwise, use as a key
// into the object.
return typeof selector === 'function' ? selector(data) : data[selector]
}
然而,它给了我以下错误:
Type 'Result | Data[KeysWithValueOfType<Data, Result>]' is not assignable to type 'Result'.
'Result' could be instantiated with an arbitrary type which could be unrelated to 'Result | Data[KeysWithValueOfType<Data, Result>]'.ts(2322)
如果我试着分解三元运算符:
function getValue<Data extends Aggregate, Result>(
selector: Selector<Data, Result>,
data: Data
): Result {
// If the accessor is a string, evaluate and return it.
if (typeof selector === 'function')
return selector(data)
// Use the accessor
return data[selector]
}
看起来像这样:
return data[selector]
我得到一个稍微不同的消息:
Type 'Data[KeysWithValueOfType<Data, Result>]' is not assignable to type 'Result'.
'Result' could be instantiated with an arbitrary type which could be unrelated to 'Data[KeysWithValueOfType<Data, Result>]'.ts(2322)
是否有一种方法可以完成我正在寻找的?
我现在使用的是Typescript 4.6.3。
我还创建了一个代码沙箱,显示问题,错误是在getValue
走向结束:
https://codesandbox.io/s/selector-example-0gbfhm?file=/src/index.ts
您没有指定Data
的形状。TypeScript不知道用任何键索引data
会导致Result
类型的结果。
很难知道以下解决方案是否适用于您的用例,但是您可以向Data
到extends Record<string, Result>
添加约束:
function getValue<Data extends Record<string, any>, Result>(
selector: Selector<Data, Result>,
data: Data
): Result {
// If the accessor is a string, evaluate and return it.
if (typeof selector === 'function')
return selector(data)
// Use the accessor
return data[selector]
}
也许你可以添加一些例子,你调用函数,看看这是否适合所有的用例?