简体   繁体   中英

Typescript not inferring correct type after type check inside a ternary operator

I have this component that takes an error prop that might be null , string or 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 is complaining that props.error could be null . But at that point, I've already made the check Array.isArray(props.error) . So, there's no way the props.error could be null .

How can I fix this?

It seems that this TSLint rule does not support JSX very well:

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

However, it is recommended to use Elvis operator "?." but in your case it's not possible due to the "-1" operation. So you have to test props.error again:

In your case :

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

I had a similar error when using map() on an array with possible different types. You did a check for null and a check for an array so when those checks are passed you can be sure that your error props are an array of strings, you can do something like this:

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

Or you can use the string[] directly on the props.error in your shorthand if statement

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

Adding an additional null check:

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

Using the ! operator ! operator to define this property as not null:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM