打字稿-通用类型变量:不能将类型“ T”分配给类型“ T”。存在两个与此名称不同的类型,但它们不相关

时间:2018-09-18 01:22:28

标签: typescript generics contravariance typescript3.0

使用打字稿3.0+。请参阅以下涉及泛型类型变量的简单设置:

abstract class BaseClass {
  public abstract merge<T>(model?: T): T;
}

class MyClass extends BaseClass {

  public Value: string;

  public merge<MyClass>(model?: MyClass): MyClass {
    this.Value += model.Value; // <--Property 'Value' does not exist on type 'MyClass'

    return this; // <--Type 'this' is not assignable to type 'MyClass'.
                 //    Type 'MyClass' is not assignable to type 'MyClass'.
                 //    Two different types with this name exist, but they are unrelated.
  }
}

我注意到Typescript编译器描述的错误,但这些错误对我来说没有意义。为什么会这样呢?


已更新

我现在了解到,MyClass中merge方法上方的原始代码正在定义一个新的泛型类型变量,其名称与“ MyClass”相同,从而解释了错误。因此,我进行了如下所示的更改。这仍然会产生错误,我在merge方法上方做了评论:

abstract class BaseClass {
  public abstract merge<T>(model?: T): T;
}

class MyClass extends BaseClass {

  public Value: string;

/*
Property 'merge' in type 'MyClass' is not assignable to the same property in base type 'BaseClass'.
  Type '(model?: MyClass) => MyClass' is not assignable to type '<T>(model?: T) => T'.
    Types of parameters 'model' and 'model' are incompatible.
      Type 'T' is not assignable to type 'MyClass'.
*/
  public merge(model?: MyClass): MyClass {
    this.Value += model.Value;

    return this;
  }
}

为什么我不能在这里使用MyClass作为变量类型?实际上,我似乎无法用任何其他能使其正常工作的类型(例如字符串,数字,另一个类)代替它。

即使我尝试将T定义为扩展BaseClass的类型,也是如此:

abstract class BaseClass {
  public abstract merge<T extends BaseClass>(model?: T): T;
}

这仍然在MyClass中生成相同的错误。请注意,这在TypeScript 2.2.1下可以正常工作。我只注意到这不适用于任何TypeScript 2.4+版本。

1 个答案:

答案 0 :(得分:3)

<MyClass>中的public merge<MyClass>引入了另一种类型(泛型),它与class MyClass不同,但名称相同。对该通用类型一无所知,因此会出现错误Property 'Value' does not exist on type 'MyClass'

类型为this的{​​{1}},class MyClass是通用类型。

如果基类将方法定义为model,则派生类需要使用相同的定义。您曾保证在基类中将处理任何参数(无任何限制的通用T),不能仅将其限制为派生类中的merge<T>(model?: T): T