我想定义一个功能如下:
const result = evaluate({x: () => 2 * 3, y: () => "hello"})
result
的值是:
{x: 6, y: "hello"}
据我所知,该定义必须类似于:
function evaluate<T>(obj: Record<keyof T, () => T[keyof T]>): T {
// Copy the key-value pairs, invoking each value.
// There are a few different ways to do this.
return Object.assign({}, ...Object.entries<() => T[keyof T]>(obj).map(([k, v]) => ({[k]: v()})))
}
但是,这不太起作用。在前面提供的示例中,result
的类型推断为:
{x: unknown, y: unknown}
如果明确提供了type参数,则功能调用会正常工作:
const result = evaluate<{x: number, y: string}>({x: () => 2 * 3, y: () => "hello"})
是否可以通过某种方式使类型推断正常工作?
答案 0 :(得分:2)
我认为TS不够聪明,无法以这种方式解析T
。
解决方案很简单,您可以在T
中捕获参数的类型,然后使用自定义映射类型将参数转换为所需的类型:
const result = evaluate({x: () => 2 * 3, y: () => "hello"})
function evaluate<T extends Record<keyof T, () => any>>(obj: T): {
[P in keyof T]: ReturnType<T[P]>
} {
// Copy the key-value pairs, invoking each value.
// There are a few different ways to do this.
return Object.assign({}, ...Object.entries<() => T[keyof T]>(obj).map(([k, v]) => ({[k]: v()})))
}