#javascript #typescript #inheritance
#typescript
Вопрос:
Почему компилятор неявное приведение типов не работает для свойств с буквальным типом, которые являются реализациями расширенного интерфейса?
Пример:
// typescript 3.4.5
interface INumContainer {
num?: 1 | 2;
}
class myClass implements INumContainer {
// does not compile
// error TS2416: Property 'num' in type 'myClass' is not assignable to the same property in base type 'INumContainer'.
// Type 'number' is not assignable to type '1 | 2 | undefined'.
num = 1;
anotherNum: 1 | 2 = 1; // compiles
}
Ответ №1:
Члены класса контекстуально не типизируются типами, для расширения или реализации которых они объявлены, по крайней мере, начиная с TS3.7. extends
implements
Объявления or приводят к проверке типа расширяемого / реализующего класса, но это происходит позже. Это долгое время было проблемой.
Здесь происходит то, что литеральные типы, подобные 1
или 2
number
расширенные, содержат типы, подобные, если они не находятся в нерасширяющемся контексте. И поскольку myClass.num
контекстуально не типизируется INumContainer["num"]
, он расширяется до number
, что считается несовместимым.
Исходная проблема, связанная с этим для свойств, — microsoft / TypeScript # 3667. Была попытка исправить это, но в конечном итоге она была отклонена / оставлена из-за плохой совместимости с некоторыми реальными библиотеками кода.
И с тех пор мало что произошло. Похоже, что в настоящее время открытым вопросом по этой теме является microsoft / TypeScript #32082, поэтому, если вы хотите увидеть это решение, вы можете перейти к этому вопросу и дать ему 👍 или какое-либо другое подтверждение поддержки.
До тех пор вам просто придется избыточно аннотировать свои инициализаторы. Извините, у меня нет лучшего ответа для вас. Надеюсь, это поможет; удачи!