Нужно принять во внимание две точки зрения. Код, который создает запись, и код, который использует запись. Этот тип означает, что если вы создаете Entry, то entryItem может быть бананом или яблоком. У вас больше возможностей, чем было бы в противном случае.
Но что касается кода, который использует Entry, он содержит меньше информации, чем было бы в противном случае. Вы можете иметь дело с яблоком или бананом. Невозможно определить автоматически, поэтому по умолчанию вы можете получить доступ только к свойствам, которые гарантированно присутствуют. Ie, свойства найдены для обоих типов.
Если вы хотите написать код, который взаимодействует конкретно с яблоками или, в частности, с бананами, вам сначала нужно написать код, который выясняет, с каким из них вы имеете дело .
Один из способов сделать это - использовать оператор in
, чтобы узнать, присутствует ли свойство:
const Example = (entry: Entry) => {
if ('appleTitle' in entry.entryItem) {
// Inside this block, typescript knows that item must be an Apple, so you can access things found only on apples.
console.log(entry.entryItem.appleTitle);
} else {
console.log(entry.entryItem.bananaTitle);
}
}
Другой вариант - изменить ваши типы на « размеченное объединение". Другими словами, у обоих типов есть свойство, которое может однозначно идентифицировать то, с чем мы имеем дело. Например:
export type Banana = {
type: 'banana',
number: number
bananaTitle: string
}
export type Apple = {
type: 'apple',
number: number
appleTitle: string
}
// then use it like:
const Example = (entry: Entry) => {
if (entry.entryItem.type === 'apple') {
// Inside this block, typescript knows that item must be an Apple, so you can access things found only on apples.
console.log(entry.entryItem.appleTitle);
} else {
console.log(entry.entryItem.bananaTitle);
}
}
Третий вариант - создать охранник определяемого пользователем типа