Невозможно скомпилировать angular Ошибка вывода типа - PullRequest
1 голос
/ 03 апреля 2020
interface Course {
  name: string;
  lessonCount: number;
}
interface Named {
  name: string;
}

let named: Named = {
name: 'Name goes here'
};

let course: Course = {
name: 'Components and Directives',
lessonCount: 20
};

named = {name: 'dfdf'};
course =  {name: 'sfdsf', lessonCount: 25};

named = course;
course = named;

named = {name: 'sfdsf', lessonCount: 25}; почему это не компилируется?

named = course; / / почему это компилируется правильно

Имеет ли выше 2 строки НЕ одно и то же ?? Я в основном из Java фона.

Ответы [ 2 ]

1 голос
/ 03 апреля 2020

Это немного необычный случай в 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;

Это также подробно объясняется здесь

Обратите внимание, что наш объект на самом деле имеет больше свойств, чем этот, но компилятор только проверяет, что по крайней мере те, которые требуются, присутствуют и соответствуют требуемые типы.

1 голос
/ 03 апреля 2020

когда вы говорите

named = {name: 'sfdsf', lessonCount: 25};

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

когда вы говорите

named = course

компилятор ts думает, что вы назначаете объект курса со структурой курса названному объекту структуры имени. он проверяет, можно ли выполнить такое назначение. потому что в обоих есть общее имя элемента, это позволяет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...