Last updated: Feb 27, 2024
Reading timeยท3 min
To create a union type from an array:
as const
to convert the array to a readonly
tuple.typeof arr[number]
to get a type containing all of the array's
elements.// ๐๏ธ const sizes: readonly ["small", "medium", "large"] const sizes = ['small', 'medium', 'large'] as const; // ๐๏ธ type SizesUnion = "small" | "medium" | "large" type SizesUnion = typeof sizes[number];
We used as const
to set the properties of the array to readonly
and indicate
to the language that the type of the expression will not be widened, e.g. from
['small', 'medium']
to string[]
.
The as const
syntax is called a const assertion
in TypeScript.
The array in the example becomes a readonly
tuple, so its contents cannot be
changed.
// ๐๏ธ const sizes: readonly ["small", "medium", "large"] const sizes = ['small', 'medium', 'large'] as const; // โ๏ธ Error: Property 'push' does not exist // on type 'readonly ["small", "medium", "large"]' sizes.push('test');
If you try to change the contents of the array, you will get an error.
This way TypeScript can infer the type of the array as
['small', 'medium', 'large']
and not string[]
.
The typeof operator allows us to get the type of a variable.
// ๐๏ธ const sizes: readonly ["small", "medium", "large"] const sizes = ['small', 'medium', 'large'] as const; // ๐๏ธ type SizesUnion = "small" | "medium" | "large" type SizesUnion = typeof sizes[number]; // ๐๏ธ type T = readonly ["small", "medium", "large"] type T = typeof sizes;
Arrays have a numeric index signature.
// ๐๏ธ const sizes: readonly ["small", "medium", "large"] const sizes = ['small', 'medium', 'large'] as const; // ๐๏ธ ['0', '1', '2'] console.log(Object.keys(sizes));
This is why we used the [number]
syntax to get a union containing all of the
values in the array.
We are basically getting all of the values in the array that can be indexed with
a number
key.
I've also written an article on how to get the type of the array elements from an array type.
If you need to create a union type from an object's values or keys:
as const
to set the properties of the object to readonly
.keyof typeof
to get a type of the keys in the object.// ๐๏ธ const obj: {readonly name: "Bobby Hadz"; readonly country: "Chile";} const obj = { name: 'Bobby Hadz', country: 'Chile', } as const; // ๐๏ธ type UValues = "Bobby Hadz" | "Chile" type UValues = (typeof obj)[keyof typeof obj]; // ๐๏ธ type UKeys = "name" | "country" type UKeys = keyof typeof obj;
We used as const
to set the properties of the object to readonly
and
indicate to the language that the type of the expression will not be widened,
e.g. from {name: "Bobby Hadz"}
to {name: string}
.
The as const
syntax is called a
const assertion
in TypeScript.
The object in the example contains readonly
properties, so their values cannot
be changed.
// ๐๏ธ const obj: {readonly name: "Bobby Hadz"; readonly country: "Chile";} const obj = { name: 'Bobby Hadz', country: 'Chile', } as const; // โ๏ธ Error: Cannot assign to 'name' because it is a // read-only property. obj.name = 'James';
If you try to change the value of a property, you will get an error.
This way TypeScript can infer the type of the object as
{name: 'Bobby hadz'; country: 'Chile'}
instead of
{name: string; country: string;}
.
We used keyof typeof
to create a
union of the object's keys.
// ๐๏ธ const obj: {readonly name: "Bobby Hadz"; readonly country: "Chile";} const obj = { name: 'Bobby Hadz', country: 'Chile', } as const; // ๐๏ธ type UKeys = "name" | "country" type UKeys = keyof typeof obj;
We can use the same approach to get a union of the object's values.
// ๐๏ธ const obj: {readonly name: "Bobby Hadz"; readonly country: "Chile";} const obj = { name: 'Bobby Hadz', country: 'Chile', } as const; // ๐๏ธ type UValues = "Bobby Hadz" | "Chile" type UValues = typeof obj[keyof typeof obj]; // ๐๏ธ type UKeys = "name" | "country" type UKeys = keyof typeof obj;
We used the typeof operator to get the type of the object and then indexed the type with all of the keys to get a union containing the object's values.
I've also written a detailed article on how to create a type from an object's keys or values.