当 TypeScript 中的泛型类型不匹配时不会出现错误

Nic*_*kon 3 typescript

configure()我想知道为什么我可以在方法中提供与我的方法不同的通用接口class?在第一个no error示例中,我提供了IType<Args1>泛型类型MyClass,然后我可以简单地通过IArgs2缺少 prop 来覆盖它,并且我没有收到任何错误。有什么方法可以确保类型完全相同吗?

interface IArgs1 {
  a: string;
  b: string;
}

interface IArgs2 {
  a: string;
}

interface IArgs3 {
  d: string;
}

interface IType<T> {
  configure(args: T): void
}

// no error - even if 'b' is missing from IArgs2
class Class implements IType<IArgs1> {
  configure(args: IArgs2) {}
}

// error - because it's missing all IArgs1 attributes
class MyClass implements IType<IArgs1> {
  configure(args: IArgs3) {}
}

Run Code Online (Sandbox Code Playgroud)

cap*_*ian 7

这是因为T处于逆变位置。考虑这个例子:

interface IArgs1 {
  a: string;
  b: string;
}

interface IArgs2 {
  a: string;
}

type Covariance<T> = { box: T };

declare let args1: Covariance<IArgs1>;
declare let args2: Covariance<IArgs2>;

args1 = args2 // error
args2 = args1 // ok

Run Code Online (Sandbox Code Playgroud)

正如您可能已经注意到的那样,args2不可分配给args1. 这是相反的行为。

考虑这个例子:

type Contravariance<T> = { box: (value: T) => void };

declare let args1:  Contravariance<IArgs1>;
declare let args2:  Contravariance<IArgs2>;

args1 = args2 // ok
args2 = args1 // error

Run Code Online (Sandbox Code Playgroud)

现在,继承箭头已经发生了相反的变化。args1不再可分配给 ,args2args2可分配给args1

您的行为相同:

interface IType<T> {
  configure(args: T): void
}

Run Code Online (Sandbox Code Playgroud)

因为与方差上下文中IType<T>的相同。Contravariance

这就是为什么你在这里没有错误的原因:

// no error - even if 'b' is missing from IArgs2
class Class implements IType<IArgs1> {
  configure(args: IArgs2) { }
}
Run Code Online (Sandbox Code Playgroud)

因为IArgs1延伸IArgs2

你这里有一个错误:

// error - because it's missing all IArgs1 attributes
class MyClass implements IType<IArgs1> {
  configure(args: IArgs3) {}
}
Run Code Online (Sandbox Code Playgroud)

因为IArgs1IArgs3是完全不同的类型,没有任何关系。

在这里您可以找到有关 *-variance 主题的更多信息