I expected result
is number | never[]
.
But actually number | never[] | undefined
.
type T1 = (number | undefined)[]
const myFunc = (arr: T1, index: number) => {
const result = arr[index] === undefined ? [] : arr[index]
return result // number | never[] | undefined
}
Why does it behave like this ?
CodePudding user response:
Looks like TypeScript needs some help to infer types correctly based on your ternary expression. You can fix it in two ways:
Introduce a variable
const myFunc = (arr: T1, index: number) => {
const value = arr[index];
const result = value === undefined ? [] : value;
return result // number | never[]
}
Use the non-null assertion operator to help the compiler understand that the value will never be undefined:
const myFunc = (arr: T1, index: number) => {
const result = arr[index] === undefined ? [] : arr[index]!
return result // number | never[]
}
CodePudding user response:
TypeScript uses flow analysis to narrow down types of variables.
However, it seems unable to narrow down arr
just by checking that one of the elements is undefined:
type T1 = (number | undefined)[]
const myFunc = (arr: T1, index: number) => {
if (arr[index] === undefined) {
return []; // never[]
}
//the type of `arr` is still considered T1
let temp = arr[index]; //number | undefined
return temp;
}
Actually, I'm not sure how else should the type of arr
be represented as after the if
block (how would you represent "an array of number|undefined, except that this particular dynamic index is not undefined"?). It still makes some sense to simply fall back to T1
.
Your code uses ternary operator, but it acts similarly to my code above.
However, TypeScript can narrow down the types for a result
variable when the variable is used in a direct comparison in a flow control statement:
type T1 = (number | undefined)[]
const myFunc = (arr: T1, index: number) => {
const result = arr[index];
if (result === undefined) {
return []; // never[]
}
//the type of `result` is correctly determined as number, not undefined
return result;
}
I think arr
and result
(variables) may have their types narrowed down by control flow, but arr[index]
(an expression, not just a variable) will just be computed from the types of arr
and index
at that point.