Typescript - Переменные общего типа: Тип 'T' нельзя назначить типу 'T'.Существуют два разных типа с этим именем, но они не связаны - PullRequest
0 голосов
/ 18 сентября 2018

Использование машинописи 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 определял новую типизированную переменную общего типа с тем же именем, что и «MyClass», что объясняет ошибку. Поэтому я внес изменения, как показано ниже. Это по-прежнему выдает ошибку, которую я прокомментировал выше метода слияния:

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 голосов
/ 18 сентября 2018

<MyClass> в public merge<MyClass> вводит другой тип (универсальный), который отличается от class MyClass, но имеет то же имя.Ничего не известно об этом универсальном типе, поэтому вы получите ошибку Property 'Value' does not exist on type 'MyClass'.

this типа class MyClass, model имеет универсальный тип.

ЕслиВаш базовый класс определяет метод как merge<T>(model?: T): T, производный класс должен использовать то же определение.Вы обещали, что в базовом классе вы будете обрабатывать любой параметр (универсальный T без каких-либо ограничений), вы не можете ограничить его только MyClass в производном классе.

...