【问题标题】:Different compile-time behavior in arrow function vs function in TypeScript interface箭头函数与 TypeScript 接口中的函数不同的编译时行为
【发布时间】:2021-06-29 06:58:25
【问题描述】:

假设以下简化的 TypeScript sn-p:

interface MyInterface {
    callbackLambda: (value: string) => void;
    callbackFunction(value: string): void;
}

type MyType = "MyValue";

const myObject: MyInterface = {
    callbackLambda: (value: MyType): void => {
        console.log(value);
    },
    callbackFunction: (value: MyType): void => {
        console.log(value);
    }
};

myObject.callbackLambda("MyValue");
myObject.callbackFunction("MyValue");

此代码无法编译,因为 TypeScript 说:

Type '(value: MyType) => void' is not assignable to type '(value: string) => void'.
  Types of parameters 'value' and 'value' are incompatible.
    Type 'string' is not assignable to type '"MyValue"'.

所以,看起来函数定义编译得很好,但箭头函数定义却没有。

这是repro playground

我在文档中找不到信息,我最初的想法是它应该可以正常编译。谁能解释(并找到相关文档)为什么在这种情况下函数定义编译得很好而不是箭头函数?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您是否使用strictFunctionTypes 标志? (doc)

    --strictFunctionTypes 函数类型下,参数位置以逆变方式而不是双变量方式进行检查。 [...] 更严格的检查适用于所有函数类型,但源自方法或构造函数声明的函数类型除外。专门排除方法是为了确保泛型类和接口(例如Array<T>)继续大部分协变相关。

    如果是这样,我认为原因是A => C 确实不是B => C 的子类型,因为AB 的子类型(协方差)。 实际上,A => CB => C 的超类型,如果 AB 的子类型(逆变)。

    如果这听起来很奇怪,假设您有一个 Animal => void 类型的常量 washAnimal。你不能给它分配一个函数Dog => void,即使是Dog ≤ Animal,因为你不能通过Cat来调用washAnimal

    Herehere 你可以找到比我更好的协变/逆变解释。

    【讨论】:

    • 我在 TypeScript 文档中找到了关于方差的链接,但无法弄清楚为什么箭头函数与常规函数有任何不同。我猜丢失的信息是 TypeScript 编译器标志(用于不破坏现有的 DOM 和其他现有的不一致)。在这种情况下,参数应该始终是一个字符串,并且调用应该始终有效,但对于其他类型可能并非总是如此。
    猜你喜欢
    • 2018-03-11
    • 2018-01-25
    • 2022-01-18
    • 2018-06-29
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多