为什么 TypeScript 不强制执行接口签名?

dou*_*oup 5 typescript

所以,我有以下界面:

interface DoStuffInterface {
    doStuff(value: string | number): string | number;
}
Run Code Online (Sandbox Code Playgroud)

为什么在实现这个接口时TS不强制签名?

class NumberStuff implements DoStuffInterface {
    public doStuff(value: number): string | number { // <====== missing: | string
        return value;
    }
}

class StringStuff implements DoStuffInterface {
    public doStuff(value: string): string | number { // <====== missing: | number
        return value.toLowerCase();
    }
}
Run Code Online (Sandbox Code Playgroud)

这很容易被这样的东西打破:

var numberStuff = new NumberStuff();
var stringStuff = new StringStuff();

function run(thing: DoStuffInterface): void {
    console.log(thing.doStuff(42));
}

run(numberStuff);
run(stringStuff); // <====== this fails, due to: `42.toLowerCase()`
Run Code Online (Sandbox Code Playgroud)

那么,为什么 TS 不强制NumberStuff&StringStuff拥有正确的签名呢?如果签名设置正确,这将是一个编译时错误,而不是一个运行时错误。

我是否缺少一些配置标志?或者这是预期的行为?

这里是完整的例子

Ale*_* L. 2

TLDR 启用属性所需的行为更改方法:

interface DoStuffInterface {
    doStuff: (value: string | number) => string | number;
}
Run Code Online (Sandbox Code Playgroud)

操场


对于strictFunctionTypes下的接口,函数类型参数位置以逆变方式检查(对于“function prop”),而不是双变量检查(对于方法)

更严格的检查适用于所有函数类型,除了源自方法或构造函数声明的函数类型。专门排除方法是为了确保泛型类和接口(例如Array<T>)继续大部分协变相关。