Kishore
Kishore

Reputation: 27

TypeScript Distributive Conditional Types - additional type parameter constraints

I am trying to understand Conditional Types introduced in TypeScript 2.8 and reading the below official documentation.

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html

In Distributive conditional types, there is an example

type BoxedValue<T> = { value: T };
type BoxedArray<T> = { array: T[] };
type Boxed<T> = T extends any[] ? BoxedArray<T[number]> : BoxedValue<T>;

type T20 = Boxed<string>;  // BoxedValue<string>;
type T21 = Boxed<number[]>;  // BoxedArray<number>;
type T22 = Boxed<string | number[]>;  // BoxedValue<string> | BoxedArray<number>;

In the above example, i didn't understand the meaning of T[number] in BoxedArray<T[number]>

Is it referring to the first element of the Array passed or what is happening here?

Can someone please help me explain this.

Thanks in advance.

Upvotes: 1

Views: 236

Answers (2)

jcalz
jcalz

Reputation: 327994

It's a "lookup type" or "indexed access type". A[B] is the type of the value you get when indexing into an object of type A with a key of type B. So T[number] is what you get when you index into an object of type T with a numeric key. Note that such a type will only compile if T is known to have a numeric index signature... for example, if T is an array type, then T[number] is the type of the elements of the array.

Thus, T extends any[] ? BoxedArray<T[number]> : BoxedValue<T> means "for each union member of T: if it is an array type, produce a BoxedArray of its element type; otherwise, produce a BoxedValue of it, and join them all up in a single union", as the examples show.

Hope that helps; good luck!

Upvotes: 3

lukasgeiter
lukasgeiter

Reputation: 152870

That's (another) use of lookup types. Basically think of T[number] as the type of any element accessible by any numeric index.

For a uniform array (every element has the same type) this is the same as doing T[0] which returns the type of the first element.


However this is not always the case. That's because TypeScript also has the concept of tuples.

Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same.

Let's say we have this tuple:

type Tuple = [string, number, string];

The first element and the last will be of type string, but the second one is a number. Using a lookup type we can access the different indices:

Tuple[0] // -> string
Tuple[1] // -> number
Tuple[2] // -> string

So if we use number in the lookup type we don't get the type of one single element, but a union of all possible types:

Tuple[number] // -> string | number

Upvotes: 3

Related Questions