Почему в этом примере не работает защита типов машинописного текста?

Мой пример - это следующий код:

type SomeType = {
    name: string,
    age: number,
} | {
    xy: [number, number]
}


function someFunction(arg: SomeType) {
    if (arg.name && arg.age) {
        // DO STH
    } else if (arg.xy) {
        // DO STH
    }
}

Почему машинописный текст показывает мне следующие сообщения об ошибках?

При наведении курсора на arg.xy  введите описание изображения здесь

При наведении курсора на arg.name или arg.age:  введите описание изображения здесь


person MeineHTMLCodes    schedule 07.07.2021    source источник
comment
Я бы сказал, что сообщение об ошибке не совсем точное, но предупреждение говорит вам, что вы не можете быть уверены, что ссылаетесь на это свойство. Если у вас есть тип any, вы также должны ссылаться на name с arg['name'] вместо arg.name, даже если вы знаете, что он существует.   -  person Christian    schedule 07.07.2021


Ответы (1)


Когда у вас есть объединение типов, вы можете получить доступ только к свойствам, которые существуют для всех типов. Так, например, вы не можете получить доступ к name, потому что { xy: [number, number] } не имеет свойства name.

Вместо этого используйте оператор in, чтобы проверить, существует ли свойство:

if ("name" in arg) {
  // in this block, arg is narrowed to being { name: string, age: number }
} else {
  // in this block, arg is narrowed to being { xy: [number, number ] }
}

Playground ссылка

Другой вариант - изменить ваши типы, чтобы получить размеченный союз. Т.е. у вас есть определенное свойство, которое существует для всех членов объединения, но каждый отдельный тип имеет свое значение. Поскольку он есть у всех типов, вы всегда можете получить к нему доступ. А поскольку он уникален, его проверка может сказать вам, с чем вы имеете дело.

type Example = {
  type: 'person',
  name: string,
  age: number,
} | {
  type: 'coordinate',
  xy: [number, number]
}

function someFunction (arg: Example) {
  if (arg.type === 'person') {
    // do something with the person object
  }
}

Playground ссылка

person Nicholas Tower    schedule 07.07.2021
comment
Большое спасибо! Хотя это странно, что есть разница между "property" in object и Boolean(object.property). - person MeineHTMLCodes; 07.07.2021