【问题标题】:TypeScript: Inferring the correct type for a function that evaluates function properties on a generic objectTypeScript:为评估泛型对象的函数属性的函数推断正确的类型
【发布时间】:2020-04-14 17:11:10
【问题描述】:

我想定义一个像这样工作的函数:

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}

如果明确提供类型参数,则函数调用按预期工作:

const result = evaluate<{x: number, y: string}>({x: () => 2 * 3, y: () => "hello"})

有什么方法可以让类型推断正常工作吗?

【问题讨论】:

  • 相关问题似乎是this one,为什么不能从keyof 函数参数类型正确推断出对象文字。我认为,不是属性值类型是 {},而是在某个时间点将其更改为 unknown 作为常见的超类型

标签: typescript generics types type-inference typescript-generics


【解决方案1】:

我认为 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()})))
}

Playground Link

【讨论】:

  • 哇!我不知道 ReturnType。谢谢!这让我发疯了。
猜你喜欢
  • 2018-08-07
  • 2020-09-09
  • 2019-12-09
  • 2017-06-02
  • 2016-11-01
  • 1970-01-01
  • 2019-03-31
  • 2019-09-08
  • 2020-01-23
相关资源
最近更新 更多