typescript 为什么子类类型不能赋值给泛型扩展类型?

rdlzhqv9  于 2023-02-17  发布在  TypeScript
关注(0)|答案(1)|浏览(216)

下面的代码给出了一个错误(如下)。但是如果我把Parent.method()的返回类型改为A,它就会编译。这背后的逻辑是什么?为什么B不能赋值给T,因为它是从A扩展而来的?
TS2416:类型“Child”中的属性“method”不能赋给基类型“Parent”中的同一属性。 类型“()=〉B”不能赋值给类型“()=〉T”。 类型“B”不能赋值给类型“T”。 “B”可分配给类型为“T”的约束,但“T”可以用约束“A”的其他子类型示例化。

class A {}

class B extends A {}

class Parent {
     public method<T extends A>(): T { // <---- return type
        ...
    }
}

class Child extends Parent {
    public method(): B {
        ...
    }
}
mspsb9vt

mspsb9vt1#

你问
既然B从A延伸,为什么B不能赋值给T呢?
但编译器说的问题稍有不同:
"B"可分配给类型为"T"的约束,但"T"可以用约束"A"的其他子类型示例化。
例如,您可以:

class C extends A {}

const p1 = new Parent();
const r1 = p1.method<C>();

r1的预期类型为C,如果允许具有固定返回类型B的重载,则可能导致运行时错误。
在这个特殊的例子中,我手动强制泛型参数为C,但是如果它是从一个参数中推断出来的,情况非常相似。

class A {}

class B extends A {}

class C extends A {}

class Parent {
     public method<T extends A>(p: T): T {
      return p;
    }
}

class Child extends Parent {
    public method(p: B): B { // Compiler error
      return p
    }
}

const p1 = new Parent();
const r1 = p1.method(new C());

const c2 = new Child();
const r2 = c2.method(new C());

console.log(r2);  // prints C, but inferred type is B

相关问题