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

w9apscun  于 2023-05-08  发布在  TypeScript
关注(0)|答案(1)|浏览(123)

在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 ?
zpgglvta

zpgglvta1#

方法参数在 typescript 中表现为双变量。有一个proposal可以使它们的行为发生逆变,但由于它自2016年以来一直开放,因此它可能不是优先事项。
有一个选项(strictFunctionTypes)可以使函数签名的参数不起源于方法,但方法显式地免于更严格的检查。从PR中引入了这种更严格的函数模式,我们可以了解方法豁免背后的原因:
方法被特别排除在外,以确保泛型类和接口(如Array)继续以协变方式关联。严格检查方法的影响将是一个更大的破坏性变化,因为大量的泛型类型将变得不变(即使如此,我们可能会继续探索这种更严格的模式)。

相关问题