【问题标题】:Why can't typescript infer an argument's type if it is a generic function using `keyof`?如果它是使用`keyof`的通用函数,为什么打字稿不能推断参数的类型?
【发布时间】:2018-06-16 11:50:22
【问题描述】:

为什么会报错?

type MyType = {
    a: string, b: string
}


function cantInfer<In, Out>(fn: (i: In) => Out, i: In) {

}

function myFunction<K extends keyof MyType>(key: K): string {
    return '';
}

cantInfer(myFunction, 'a');

但这不是:

type MyType = {
    a: string, b: string
}


function cantInfer<In, Out>(fn: (i: In) => Out, i: In) {

}

function myFunction(key: keyof MyType): string {
    return '';
}

cantInfer(myFunction, 'a');

注意,myFunction 中缺少的&lt;K extends keyof MyType&gt;

【问题讨论】:

  • 问题是它无法推断出 K,因为它根本没有用在 myFunction 的参数和返回值中。你试过function myFunction&lt;K&gt;(key: K): string
  • 刚刚更新为更好的示例。感谢您指出这一点。

标签: typescript


【解决方案1】:

应该注意的是,当strictFunctionTypes 被禁用时,您的第一个示例会进行类型检查。这将禁用函数类型的双变量参数检查。如果没有此检查,编译器将允许在运行时可能不健全的代码。

可以找到很好的解释here:

... 一个更具体的类型接受函数是否应该分配给一个接受不太具体类型的函数的问题提供了一个先决条件答案,即该更具体类型的数组是否应该分配给一个数组一种不太具体的类型。在绝大多数情况下,如果不是后者,则不是可接受的类型系统,因此我们必须针对函数参数类型的特定情况进行正确性权衡。

您在第二个示例中通过将myFunction 的类型参数具体化来解决问题:keyof MyType 在编译时解析为string,这意味着myFunction 的类型签名实际上是myFunction(key: string): string

以下示例通过相反的方式进行类型检查 - 它使 canInfer 上的类型约束不那么宽松 (playground link):

type MyType = {
    a: string, b: string
}

function canInfer<In extends keyof MyType, Out>(fn: (i: In) => Out, i: In) {
    return fn(i);
}

function myFunction<K extends keyof MyType>(key: K): string {
    let myType = {
        a: "foo",
        b: "bar"
    }
    return myType[key];
}

alert(canInfer(myFunction, 'a'));

【讨论】:

    猜你喜欢
    • 2021-01-03
    • 2020-03-01
    • 1970-01-01
    • 2022-09-29
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-13
    相关资源
    最近更新 更多