Home > Software engineering >  Unsafe assignment of an Any value ternary operator
Unsafe assignment of an Any value ternary operator

Time:05-18

I have a doubt related to typescript, and how I can work with union types to make it work. Currently I have this code:

   const message: string | string[] = (axiosError as Error).message
    const errorState: string | string[] = Array.isArray(message)
      ? message[0]
      : message

The issue I get is in errorStat variable, I know the cause, it is because I am trying to access message[0] and it can be of type string and have no data inside. I know I always got a value inside message.

Any help?

Thanks!

CodePudding user response:

There are a number of places where this will trip up.

The biggest one is that Array.isArray and the other answerer's isArray type guards only assert whether or not the given type is any[], not any particular T[]. If the type guard fails, the type checker knows for sure the type is string. But if it passes, the type checker only knows that it's any[] and can't figure out anything beyond that.

If, instead, you had this type guard:

function isTypedArray<T>(val: T | T[]): val is T[] {
    return isArray(val);
}

Then the type checker will be able to differentiate between string and string[].

However, you're then storing it in a variable that you have explicitly typed as string | string[], so when you subsequently try to use errorMessage, the type checker will still be confused about the type. Remove the type annotation from errorMessage, or change it to just string.

Finally, this might not be an issue for your particular use case, but you have a potential bug if axiosError's message field is an empty array. The type checker will assert that you have an array, but then when you try to access the value of it at runtime, it will return as undefined. That might be acceptable in your situation, but I don't know.

CodePudding user response:

Array.isArray() is not a typeguard. You can create one of your own using the is keyword.

Since you only want to check for an array you can use this. Here is an isArray type-predicate:

  let message: string | string[] = 'sdsd';
  const isArray = (arg: any): arg is any[] => {
   return Array.isArray(arg);
}
    const errorState: string | string[] = isArray(message)
      ? message[0]
      : message

Here is an isStringArray predicate for your use:

const isStringArray = (arg: any): arg is string[] => {
    for(let i = 0 ; i < arg.length; i  ){
      if(typeof arg !== 'string') 
        return false;
    }
   return Array.isArray(arg);
}
  • Related