Update: based on @jerico's answer below
The following type alias will return the type of the elements in an array or tuple:
type ArrayElement<ArrayType extends readonly unknown[]> =
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
So these examples would work:
type A = ArrayElement<string[]>; // string
type B = ArrayElement<readonly string[]>; // string
type C = ArrayElement<[string, number]>; // string | number
type D = ArrayElement<["foo", "bar"]>; // "foo" | "bar"
type E = ArrayElement<(P | (Q | R))[]>; // P | Q | R
type Error1 = ArrayElement<{ name: string }>;
// ^^^^^^^^^^^^^^^^
// Error: Type '{ name: string; }' does not satisfy the constraint 'readonly unknown[]'.
Explanation
The type guard (the bit in the angle brackets) ArrayType extends readonly unknown[] says that we expect the type parameter ArrayType to be at least a readonly array (it also accepts a mutable array) so that we can look at its element type.
This prevents passing in a non-array value, as in the final example, which prevents ArrayElement ever returning never.
Note that readonly unknown[] is syntax added in TypeScript 3.4; for earlier versions use ReadonlyArray<unknown>.
On the right-hand side, the conditional expression asks the compiler to fill in the value of ElementType in the pattern readonly ElementType[] and return ElementType if it can, or never if it can't.
Since the type guard at the beginning means we will only ever be passed a value which matches this pattern, it's guaranteed always to match and never to return never.
Previous answer
type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType[number];
Answer from Will Madden on Stack OverflowUpdate: based on @jerico's answer below
The following type alias will return the type of the elements in an array or tuple:
type ArrayElement<ArrayType extends readonly unknown[]> =
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
So these examples would work:
type A = ArrayElement<string[]>; // string
type B = ArrayElement<readonly string[]>; // string
type C = ArrayElement<[string, number]>; // string | number
type D = ArrayElement<["foo", "bar"]>; // "foo" | "bar"
type E = ArrayElement<(P | (Q | R))[]>; // P | Q | R
type Error1 = ArrayElement<{ name: string }>;
// ^^^^^^^^^^^^^^^^
// Error: Type '{ name: string; }' does not satisfy the constraint 'readonly unknown[]'.
Explanation
The type guard (the bit in the angle brackets) ArrayType extends readonly unknown[] says that we expect the type parameter ArrayType to be at least a readonly array (it also accepts a mutable array) so that we can look at its element type.
This prevents passing in a non-array value, as in the final example, which prevents ArrayElement ever returning never.
Note that readonly unknown[] is syntax added in TypeScript 3.4; for earlier versions use ReadonlyArray<unknown>.
On the right-hand side, the conditional expression asks the compiler to fill in the value of ElementType in the pattern readonly ElementType[] and return ElementType if it can, or never if it can't.
Since the type guard at the beginning means we will only ever be passed a value which matches this pattern, it's guaranteed always to match and never to return never.
Previous answer
type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType[number];
Since 2.1, typescript supports [ ] operator for types. The official name is indexed access types, also called lookup types, and it works like this:
type A = {a: string, b: number} [];
type AElement = A[0];
let e: AElement = {x: 0}; //error TS2322: Type '{ x: number; }' is not
//assignable to type '{ a: string; b: number; }'
Get array element as type?
typescript - How to get type of array items? - Stack Overflow
In Typescript how do you get an element type from an array type, when the array contains different element types? - Stack Overflow
typescript - How can I get the type of array items? - Stack Overflow
Videos
Is it possible to have a function that takes a parameter of type T[] and has a return type of "element of the parameter" (not the general type T)?
In other words, if I write "const x = myFunc([1, 2])", can I type myFunc in a way that the compiler knows x can only be 1 or 2 at compile time?
I tried for a while but could not figure it out. The only thing that worked was declaring the array "as const" before passing it in, but I would like to solve this through typing the function instead, if possible.
If you're looking to how to extract { name: string; test: number; } type, you can simply create alias to "item at index":
type Foo = Array<{ name: string; test: number; }>;
type FooItem = Foo[0];
or
type FooItem = Foo[number];
Starting with TypeScript 2.8 you can also do this with the infer keyword. This should only be used for more complicated cases (arrays nested in promises, etc), otherwise it is overly verbose.
type GetElementType<T extends any[]> = T extends (infer U)[] ? U : never;
For example:
// ElementType === string
type ElementType = string[] extends (infer U)[] ? U : never;
The infer keyword is very powerful and can extract any type out of larger type. For example if the type was a function that returns an array:
type FncType = () => [{ name: string }];
// Output === { name: string }
type Output = FncType extends () => (infer U)[] ? U : never;
You can also use the infer keyword in generic types:
type GetArrayReturnType<T> = T extends () => (infer U)[] ? U : never;
// Output === { name: string }
type Output = GetArrayReturnType<() => [{ name: string }]>;
You can use this format to get the member type:
type InputType = typeof input[number];
You can read more about it (and some other cool tips) here in Steve Holgado's blog article.
You can extract it by pointing at an array member, so while you are using the below code to get the type of the array:
type A = typeof input;
You can use this to get the type of a single item:
type B = typeof input[0];
If you're looking to how to extract { name: string; test: number; } type, you can simply create an alias to "item at index":
type Foo = Array<{ name: string; test: number; }>;
type FooItem = Foo[0];
or
type FooItem = Foo[number];
Starting with TypeScript 2.8, you can also do this with the infer keyword. This should only be used for more complicated cases (arrays nested in promises, etc.). Otherwise, it is overly verbose.
type GetElementType<T extends any[]> = T extends (infer U)[] ? U : never;
For example:
// ElementType === string
type ElementType = string[] extends (infer U)[] ? U : never;
The infer keyword is very powerful and can extract any type out of larger type. For example, if the type was a function that returned an array:
type FncType = () => [{ name: string }];
// Output === { name: string }
type Output = FncType extends () => (infer U)[] ? U : never;
You can also use the infer keyword in generic types:
type GetArrayReturnType<T> = T extends () => (infer U)[] ? U : never;
// Output === { name: string }
type Output = GetArrayReturnType<() => [{ name: string }]>;