Home > OS >  TypeScript: Why is undefined not an option if type is a union of empty array and array of data when
TypeScript: Why is undefined not an option if type is a union of empty array and array of data when

Time:08-27

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:

That's as design.

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
}
  • Related