const names = ['jacob', 'master jung', 'kyuhyun'] as const;
type Names = typeof names[number];
I got the results I wanted, but I don't understand typeof names[number]
.
What does typeof Array[number]
in Typescript mean?
const names = ['jacob', 'master jung', 'kyuhyun'] as const;
type Names = typeof names[number];
I got the results I wanted, but I don't understand typeof names[number]
.
What does typeof Array[number]
in Typescript mean?
There is a comment made by the user @jcalz that explains how it works. It refers to the following code, which is similar to the OP code:
const fruit = ["apple", "banana", "grape"] as const;
export type Fruit = (typeof fruit)[number]; 'apple'|'banana'|'grape';
typeof fruit
isArray<"apple" | "banana" | "grape">
, soFruit
is equivalent to(Array<"apple" | "banana" | "grape">)[number]
. The syntaxT[K]
means: the type of the properties ofT
whose keys are of typeK
. So(Array<"apple" | "banana" | "grape">)[number]
means "the types of the properties ofArray<"apple" | "banana" | "grape">
whose keys are of typenumber
", or: "the array elements ofArray<"apple" | "banana" | "grape">
, or:"apple" | "banana" | "grape"
.
And another similar comment by that user that adds a bit more technical terms:
The type
T[K]
is a lookup type which gets the type of the property ofT
whose key isK
. In(typeof list)[number]
, you're getting the types of the properties of(typeof list)
whose keys arenumber
. Arrays liketypeof list
have numeric index signatures, so theirnumber
key yields the union of all numerically-indexed properties.
typeof
gets the type of names
variable (which is readonly ['jacob', 'master jung', 'kyuhyun']
) then array/tuple member type is resolved. This is called indexed access types or lookup types.
Syntactically, they look exactly like an element access, but are written as types
In this case we "query" the type of tuple member (tuple/array at index) which is 'jacob' | 'master jung' | 'kyuhyun'
@OfirD's answer is great and I recommend reading it first, but it didn't really click for me until I saw the same concept applied to an array and an object, side-by-side.
I've taken the liberty of breaking down your original example:
I think line 5 is the most important part to understand: it takes an array type (readonly ["jacob", "master jung", "kyuhyun"]
) and returns the types that would result from indexing by a number. Since the compiler knows exactly what elements are in the array, the answer is "jacob" | "master jung" | "kyuhyun"
.
Now let's use another example, an object. We want a type of all keys, and a type of all values:
I think line 12 is the most important part to understand: it gets the type of a test
(which you can see defined on line 2), and then says, "what would be the type if we indexed it by its own keys?" As you can see, that would be a union of test
's values.
Anything with a type of Names
has to be an item in the array.
Now, you can do:
const value: Names = "jacob"