Условный тип Typescript расширяет поведение не так, как ожидалось - PullRequest
1 голос
/ 21 марта 2019

Допустим, у нас есть этот пример:

class Base<T extends Base<T>> {}
class ClassA extends Base<ClassA> {}
class ClassB extends Base<ClassB> {}
type Condition = ClassA extends ClassB ? true : false;

Базовый класс имеет один универсальный аргумент, который в основном говорит, что все производные от него должны шаблонизировать его своим собственным типом.

Тогда мыесть 2 класса, производные от указанной базы.

Наконец, я создал условный тип, который проверяет, расширяют ли производные классы друг друга.

К моему удивлению, машинопись говорит мне, что они делают,но я думаю, что это условие должно быть ложным.ClassA не распространяется ClassB и наоборот.Только ClassA extends Base<ClassA> должно возвращать true.

Это проблема условных типов машинописного текста или я что-то упустил?Я столкнулся с этой проблемой при создании более сложного условного типа, который также возвращал неожиданные результаты.

Редактировать: Общие аргументы также не нужны.Даже этот пример возвращает неверный результат:

class Base {}
class ClassA extends Base {}
class ClassB extends Base {}
type Condition = ClassA extends ClassB ? true : false;

1 Ответ

3 голосов
/ 21 марта 2019

Typescript использует структурную типизацию, чтобы наилучшим образом эмулировать работу Javascript duck.Это имеет то преимущество, что позволяет нам моделировать множество сценариев Javascript статически.

Проблема в том, что вы никогда не должны забывать, что, когда typcript проверяет любую совместимость типов (даже в условных типах), он не проверяет номинальное наследование, как в C # или Java, а проверяет структурный подтип.

В вашем примере, поскольку все классы пусты, они структурно эквивалентны {}, что означает, что да, ClassA действительно расширяет ClassB и ClassB расширяет ClassA, так как они всеструктурно того же типа.

Добавьте любой член к классам, и это уходит, частные члены гарантируют максимальную несовместимость, потому что другой класс (или интерфейс) не может просто объявить их заново, чтобы имитировать подтип.

class Base {}
class ClassA extends Base { private a: number}
class ClassB extends Base { private b: number}
type Condition = ClassA extends ClassB ? true : false; // false now
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...