Это немного необычный случай в TypeScript
, и он кажется нелогичным и трудным для объяснения, но я постараюсь изо всех сил.
Давайте начнем с этого
named = course;
Это прекрасно компилируется, потому что интерфейс Course
имеет свойство name
, которое (обязательно) string
. То, что интерфейс и объект также имеют lessonCount
, не интересно для компилятора. Пока назначенный тип имеет все свойства, указанные в интерфейсе. Тип named
останется Named
, и если вы попытаетесь сделать named.lessonCount
после присвоения ему course
, это выдаст ошибку. Таким образом, для всех намерений и целей, согласно компилятору, named
не имеет свойства .lessonCount
, даже если вы знаете лучше. Это называется проверкой типа Lenient
Теперь, если вы выполняете присваивание Object literal
:
named = {name: 'sfdsf', lessonCount: 25};
Компилятор говорит: эй! Я вижу, вы пытаетесь присвоить этот литерал объекта моему интерфейсу Named
, но вы также определили свойство lessonCount
. Я не согласен с этим.
Согласно документам:
Однако TypeScript придерживается позиции, что в этом коде, вероятно, есть ошибка. Объектные литералы получают специальную обработку и при проверке go избыточных свойств при назначении их другим переменным или передаче их в качестве аргументов. Если у литерала объекта есть какие-либо свойства, которых нет у «целевого типа», вы получите ошибку
С другой стороны, это снова работает:
named = {name: 'sfdsf', lessonCount: 25} as Course;
Это также подробно объясняется здесь
Обратите внимание, что наш объект на самом деле имеет больше свойств, чем этот, но компилятор только проверяет, что по крайней мере те, которые требуются, присутствуют и соответствуют требуемые типы.