Can anyone explain this?
Why is undefined not an option if type is a union of empty array and array of data when accessing an item
type emptyArray = []
type accessEmptyArray = emptyArray[0] // returns undefined
type validData = {id:number, name:string}
type someData = validData[] | []
type test = someData[0] // returns type validData but could also be undefined
I assume I can solve this by using an assertion but it will make my code quite verbose.
I'm quite surprised by this issue as it seems like a problem that is easily overlooked and the type of problem that TS is built to solve but maybe I haven't thought of a downside to my assumed way of it working
Example: Playground
CodePudding user response:
Indexed access on a type will not return undefined.
type array = Array<string>;
type firstItemType = array[0] // string;
CodePudding user response:
In order to understand that, please be aware that :
type EmptyArray = []
type EmptyArray2 = never[]
both EmptyArray and EmptyArray2 are equal. Empty array, in TypeScript is infered as never[].
Try this:
type EmptyArray = []
type Item = EmptyArray[number] // never
Hence, union of both empty and non empty looks like this:
type ValidData = { id: number, name: string }
type Union = Array<ValidData> | never[]
type NonEmptyElement = Array<ValidData>[number] // ValidData
type EmptyElement = never[][number] // never
type Result = Union[0] // ValidData | never -> ValidData
When you make union of empty / non empty array and trying to obtain first element, you basically obtaining union of ValidData | never, which is equal to just ValidDate.
If you are curious why never is meaningless in any union, see this answer
As for the error in:
type emptyArray = []
type accessEmptyArray = emptyArray[0] // returns undefined
This is because emptyArray does not have any elements, and type script does not allow even to use 0, however, you are still allowed to use index of Array:
type accessEmptyArray = emptyArray[number] // never
This is because Array has this type signature:
interface Array<T> {
[n: number]: T
}
