Я создаю приложение React Native с использованием TypeScript. Мой стартап недавно перешел на TypeScript с JavaScript, и я переношу код.

У меня есть <FlatList />, который состоит из двух типов заведений: ресторана и бара. У ресторана и бара есть общие владения, но у них их нет. Например, свойство servesFood уникально для ресторанов.

Функция renderItem выглядит так:

renderItem = ({ item }: { item: Restaurant | Bar }) => {
  return item.servesFood ? (
    // ... Restaurant code
  ) : (
    // ... Bar code
  )

Проблема в том, что в условии для этого тернарного оператора TypeScript выдает ошибку:

Property 'servesFood' does not exist on type 'Restaurant | Bar'.
  Property 'servesFood' does not exist on type 'Bar'

Кроме того, в специфическом для типа коде при доступе к специфическим для типа свойствам также есть ошибки линтинга.

Примечание. По разным причинам я не могу позволить им поделиться свойством и установить для одного из них значение true для одного first и false для другого.

Итак, как я могу сообщить TypeScript, что в одной части предложения If / тернарного оператора элемент имеет тип Restaurant, а в другом элементе - тип bar, чтобы эти ошибки линтинга исчезли.

1
J. Hesters 23 Окт 2018 в 16:46

2 ответа

Лучший ответ

Вы можете использовать защиту типа, чтобы сузить тип параметра.

Вы можете использовать размеченные объединения на основе поля servesFood:

interface Restaurant{
    servesFood: true
}
interface Bar {
  servesFood?: false
}
const renderItem = ({ item }: { item: Restaurant | Bar }) => {
      return item.servesFood ? (
        // ... Restaurant code
      ) : (
        // ... Bar code
      )

Или, если интерфейсы не разделяют servesFood, вы можете использовать защиту типа in

interface Restaurant{
    servesFood: true
}
interface Bar {
  drinks: true
}
const renderItem = ({ item }: { item: Restaurant | Bar }) => {
      return 'servesFood' in item ? (
        item.servesFood
      ) : (
        // ... Bar code
        item.drinks
      );
2
Titian Cernicova-Dragomir 23 Окт 2018 в 14:16

Вы можете просто сравнить ключ / значение объекта, чтобы узнать, существует ли свойство serveFood для текущего элемента. Если значение равно null, это означает, что item не содержит свойства servesFood Что-то вроде этого:

renderItem = ({ item }: { item: Restaurant | Bar }) => {
  return ((item["servesFood"] != null) ? (
    // ... Restaurant code, it exists the property servesFood
  ) : (
    // ... Bar code, it doesn't exists the property servesFood so it is null
  ))
1
Brank Victoria 23 Окт 2018 в 14:17
52950706