There was this challenge
Implement a generic First that takes an Array T and returns its
first element’s type.
type arr1 = ["a", "b", "c"];
type arr2 = [3, 2, 1];
type head1 = First<arr1>; // expected to be 'a'
type head2 = First<arr2>; // expected to be 3
But I am confused. Since the tasks says we should return first elements type, shouldn’t return in first case be string? and in second number?
What am I missing?
Ps. This is the given solution and it indeed returns "a" instead of string
type First<T extends any[]> = T extends [] ? never : T[0];
Update:
In below code head1 is inferred as string.
let arr1 = ["a", "b", "c"]; // use let instead of type
type head1 = First<typeof arr1>;
Why when I used type array1 as in my question, head1 was inferred as "a" and above as "string"?
>Solution :
The key is that arr1 and arr2 aren’t array types; they’re tuple types. In JavaScript, tuples are simply arrays, but in TypeScript’s type system every element of a tuple has its own type.
This is easier to see if you use "actual" types instead of literals, for example:
type arr1 = [string, number, Object];
const arr1Value: arr1 = ["hello", 42, {}];
type head1 = First<arr1>; // string
Note that arr1 is not an array. It’s a type of array (or tuple), and arr1Value is an array of that type.
If you don’t provide the type of an array literal, it is inferred:
let arr1 = ["a", "b", "c"]; // arr1 is of type string[]
Now, the inferred type of arr1 could have been inferred as ['a', 'b', 'c']; that is, a tuple of those three strings. But that’s almost never what you want: for example, it wouldn’t let you push more values onto the array. So TypeScript infers that it’s a string[] instead. (If you do want to infer a tuple type, add as const at the end.)