Typescript не выводит правильный тип после проверки типа внутри троичного оператора

#javascript #reactjs #typescript #type-inference

#javascript #reactjs #typescript #вывод типа

Вопрос:

У меня есть этот компонент, который принимает error реквизит, который может быть null , string или string[] .

 
interface ErrorComponent {
  error: null | string | string[]      // props.error UNION TYPES
}

const ErrorComponent: React.FC<ErrorComponent> = (props) => {

  const errorItems = props.error ?               // CHECK IF props.error EXISTS (string | string[])
    Array.isArray(props.error) ?                 // CEHCK IF props.error IS AN ARRAY
      props.error.map((item,index) =>            // CASE string[]
        <Error_DIV 
          key={index} 
          marginBottom={index === props.error.length -1 ? "0px" : "8px"}   // GETTING WARNING FOR POSSIBLE null HERE
        >
          {item}
        </Error_DIV>
      )
    : <Error_DIV>{props.error}</Error_DIV>       // CASE string
  : null;                                        // CASE null

  // return SOMETHING
};

  

введите описание изображения здесь

Typescript жалуется, что props.error может быть null . Но на тот момент я уже выполнил проверку Array.isArray(props.error) . Таким образом, props.error не может быть null .

Как я могу это исправить?

Ответ №1:

Похоже, что это правило TSLint не очень хорошо поддерживает JSX:

 props.error.map((item,index) => 
    <Error_DIV // Here TSLINT context seems to be reset
  

Однако рекомендуется использовать оператор Elvis «?». но в вашем случае это невозможно из-за операции «-1». Поэтому вам нужно снова протестировать props.error:

В вашем случае :

 marginBottom={props.error amp;amp; index === props.error.length -1 ? "0px" : "8px"} 
  

Комментарии:

1. Спасибо. Когда я добавляю ? как в props.error?.length , я получаю объект, возможно, ‘undefined’ .

2. правильно, это потому, что «-1». Я обновил свой ответ

Ответ №2:

У меня была аналогичная ошибка при использовании map() для массива с возможными различными типами. Вы выполнили проверку на null и проверку на массив, поэтому, когда эти проверки будут пройдены, вы можете быть уверены, что ваши реквизиты ошибки представляют собой массив строк, вы можете сделать что-то вроде этого:

 (props.error as string[]).map((item,index)
  

Или вы можете использовать string[] непосредственно на props.error в вашем сокращенном выражении if

 marginBottom={index === (props.error as string[]).length -1 ? "0px" : "8px"}
  

Добавление дополнительной нулевой проверки:

 marginBottom={props.error amp;amp; index === props.error.length -1 ? "0px" : "8px"}
  

Использование ! operator для определения этого свойства как not null:

 marginBottom={index === props.error!.length -1 ? "0px" : "8px"}