为什么 TypeScript 中的方法参数不是逆变的?

And*_*aev 5 typescript

在 TypeScript 中,您可以在派生类中拥有协变方法参数。
这看起来像是公然违反LSP。
这部分语言设计的意图是什么,是故意的还是设计限制?

interface A {
    a: number;
}

interface B extends A {
    b: number;
}

class Base {
    public foo(arg0: A): B { 
        return { a: 0, b: 42 };
    }
}

class Derived extends Base {
    public foo(arg0: B): B { // covariant parameter is allowed, not OK
        return { a: +arg0.a.toPrecision(2), b: +arg0.b.toPrecision(2) }; // runtime error, b is undefined, although should have been required
    }
}

let b: Base = new Derived(); // Assign a sub class to a base class should always be ok 
b.foo({ a: 10}); // no need to pass in b, right ?
Run Code Online (Sandbox Code Playgroud)

Tit*_*mir 4

方法参数在打字稿中表现出双变量。有人提议让它们表现相反的行为,但由于它自 2016 年以来一直开放,因此它可能不是一个优先事项。

有一个选项 ( strictFunctionTypes) 可以使并非源自方法的函数签名参数表现出逆变行为,但方法明确免除更严格的检查。从引入这种更严格的函数模式的PR中,我们了解了方法豁免背后的推理:

专门排除方法是为了确保泛型类和接口(例如 Array)继续大部分协变相关。严格检查方法的影响将是一个更大的破坏性变化,因为大量泛型类型将变得不变(即便如此,我们可能会继续探索这种更严格的模式)。

  • 您可能想将其添加到您的帖子中:https://github.com/microsoft/TypeScript/issues/10717 (2认同)