首页 > 解决方案 > 为什么 TypeScript 不强制执行接口签名?

问题描述

所以,我有以下界面:

interface DoStuffInterface {
    doStuff(value: string | number): string | number;
}

为什么在实现此接口时 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();
    }
}

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

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()`

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

我错过了一些配置标志吗?还是预期的行为?

这里是完整的例子

标签: typescript

解决方案


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

interface DoStuffInterface {
    doStuff: (value: string | number) => string | number;
}

操场


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

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


推荐阅读