具有泛型参数的接口函数中的协方差 - 为什么这些函数中的一个会编译?

问题描述

我已经使用 typescript 一段时间了,但还没有深入到它的黑暗角落。现在我试图用严格模式重构我的代码,但遇到了 - 我相信 - 不应该编译的代码。请参阅下面的代码、解释和问题:

代码

class Base { }

class Child extends Base {
    public name: string = 'childName';
}

interface Foo<T> {
    // 1) fails to compile
    foo: (value: T) => void; 
    // 2) compiles but crashes
    // foo(value: T): void; 
}

const childFoo: Foo<Child> = {
    foo: (value: Child): void => console.log(value.name.toLowerCase()),// using 2) crash happens here
};

const baseFoo: Foo<Base> = childFoo; // using 1) error occurs here

baseFoo.foo(new Base());

(另见typescript playground

观察到的行为

使用函数 1) 产生以下错误

Type 'Foo<Child>' is not assignable to type 'Foo<Base>'.
  Property 'name' is missing in type 'Base' but required in type 'Child'

这是意料之中的,因为 Foo<Base>.foo 需要一个可以处理任何 Base函数,但 Foo<Child>.foo一个只能处理更特殊类型({{1} }),对吗?

使用函数 2) 编译和崩溃:

Child

虽然崩溃是意料之中的,但我根本没想到它会编译。

预期行为

1) 和 2) 都不应该用 Cannot read property 'toLowerCase' of undefined 编译。


为什么使用函数 2) 而不是函数 1) 会编译这段代码

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)