Reputation: 161
found the code first in http://www.typescriptlang.org/docs/handbook/advanced-types.html#example-1
and then found this similar code in typescript codebase: https://github.com/microsoft/TypeScript/blob/master/tests/cases/conformance/types/conditional/conditionalTypes1.ts#L75
type KnockoutObservable<T> = { object: T };
type KnockoutObservableArray<T> = { array: T };
type KnockedOut<T> = T extends any[] ?
KnockoutObservableArray<T[number]> :
KnockoutObservable<T>;
type KnockedOutObj<T> = {
[P in keyof T]: KnockedOut<T[P]>;
}
what is the T[number] mean in the code?
in the Typescript Handbook example, it said
the element type of the array as T[number]
while test in the playground(just for testing), replace T[number]
with T
or T[any]
seems no different, but can not replace with T[string]
(why?).
the [number]
after T
seems not an index.
Upvotes: 15
Views: 4332
Reputation: 71
Most likelly it's an indexed access with number to array regarding to docs;
When Flatten is given an array type, it uses an indexed access with number to fetch out string[]’s element type. Otherwise, it just returns the type it was given.
Upvotes: 0
Reputation: 7608
Array
is declared using an index signature, something like this:
interface ArrayMaybe<Element> {
[index: number]: Element;
}
(I call this ArrayMaybe
because I haven’t specifically copied Array
’s declaration, and it’s not relevant.)
Index signatures indicate that a type can have properties using any value of that type as the key or index, but with the same type of value at each such key/index. So ArrayMaybe<number>
can have values at 0
, 1
, 42
, and so on, but wherever it has such properties, the property’s value will be a number
.
Coming from the other side of things, when talking about some type T
, T[____]
references some particular property of T
. So { foo: 'bar'; }['foo']
will refer to type 'bar'
. In the case of an index signature as we see above, we can use T[number]
to refer to the type of that index signature—in the case of ArrayMaybe
, that is Element
. Which is precisely how it’s being used in your example.
You can’t use T[string]
because Array
doesn’t have a string index signature. You’re allowed to use those, but Array
doesn’t. Since it doesn’t have a string index signature, T[string]
isn’t legal. You can use T['length']
, though, since Array
does have a property with that particularly string. Using string
or number
refers to any string or number—which requires an index signature.
For an example of a string index signature, consider
interface Dictionary<Value> {
[key: string]: Value;
}
With this, we can use T[string]
when T
is some Dictionary
—and T[string]
will be Value
.
Upvotes: 19
Reputation: 647
Seems to find basic explanation here https://www.typescriptlang.org/docs/handbook/2/conditional-types.html
When Flatten is given an array type, it uses an indexed access with number to fetch out string[]’s element type. Otherwise, it just returns the type it was given.
type Flatten<T> = T extends any[] ? T[number] : T;
// Extracts out the element type
type Str = Flatten<string[]>;
type Str = string
// Leaves the type alone.
type Num = Flatten<number>;
type Num = number
T[number] will return type of T array element
Upvotes: 0