类和函数参数的通用打字稿

时间:2018-12-15 14:29:01

标签: typescript generics

我正在尝试解决一个问题,我想链接多个函数调用,并让打字稿检查我是否正确地将它们链接在一起。

export class A<T, K> {
  public foo(a: A<K, T>): A<K, T> {
    return a;
  }
}

const a1 = new A<string, number>();
const a2 = new A<string, number>();

a1.foo(a2); // does not show an error

当我将鼠标悬停在方法调用上时,我看到正确的声明。我在这里想念什么?

1 个答案:

答案 0 :(得分:1)

Typescript使用结构类型系统。如果您不使用类型参数,则没什么大不了的。在您的情况下,您确实使用类型参数,但是以递归方式使用。这可能意味着编译器将检查参数一段时间,但是将无法在A<string, number>A<number, string>之间找到明确的不兼容,因此将假定它们是兼容的。

Typescript使用务实的方法来处理类型系统。在对Javascript的结构行为进行建模时,大多数时候应该是有用的。在大多数情况下,这种方法都能很好地发挥作用,您只是发现了其中一种极端情况,它给出了一些令人惊讶的结果。 (我会犹豫地说它给出了错误的结果,因为我无法想到这种令人惊讶的类型兼容性会导致运行时错误)

好消息是,当您添加以更直接的方式使用任何类型参数的成员时,这种行为就会消失:

export class A<T, K> {
    private k!:K
    public foo(a: A<K, T>): A<K, T> {
        return a;
    }
}

const a1 = new A<string, number>();
const a2 = new A<string, number>();

a1.foo(a2); // error