1 | /**
|
2 | Convert a tuple/array into a union type of its elements.
|
3 |
|
4 | This can be useful when you have a fixed set of allowed values and want a type defining only the allowed values, but do not want to repeat yourself.
|
5 |
|
6 | @example
|
7 | ```
|
8 | import type {TupleToUnion} from 'type-fest';
|
9 |
|
10 | const destinations = ['a', 'b', 'c'] as const;
|
11 |
|
12 | type Destination = TupleToUnion<typeof destinations>;
|
13 | //=> 'a' | 'b' | 'c'
|
14 |
|
15 | function verifyDestination(destination: unknown): destination is Destination {
|
16 | return destinations.includes(destination as any);
|
17 | }
|
18 |
|
19 | type RequestBody = {
|
20 | deliverTo: Destination;
|
21 | };
|
22 |
|
23 | function verifyRequestBody(body: unknown): body is RequestBody {
|
24 | const deliverTo = (body as any).deliverTo;
|
25 | return typeof body === 'object' && body !== null && verifyDestination(deliverTo);
|
26 | }
|
27 | ```
|
28 |
|
29 | Alternatively, you may use `typeof destinations[number]`. If `destinations` is a tuple, there is no difference. However if `destinations` is a string, the resulting type will the union of the characters in the string. Other types of `destinations` may result in a compile error. In comparison, TupleToUnion will return `never` if a tuple is not provided.
|
30 |
|
31 | @example
|
32 | ```
|
33 | const destinations = ['a', 'b', 'c'] as const;
|
34 |
|
35 | type Destination = typeof destinations[number];
|
36 | //=> 'a' | 'b' | 'c'
|
37 |
|
38 | const erroringType = new Set(['a', 'b', 'c']);
|
39 |
|
40 | type ErroringType = typeof erroringType[number];
|
41 | //=> Type 'Set<string>' has no matching index signature for type 'number'. ts(2537)
|
42 |
|
43 | const numberBool: { [n: number]: boolean } = { 1: true };
|
44 |
|
45 | type NumberBool = typeof numberBool[number];
|
46 | //=> boolean
|
47 | ```
|
48 |
|
49 | @category Array
|
50 | */
|
51 | export type TupleToUnion<ArrayType> = ArrayType extends readonly unknown[] ? ArrayType[number] : never;
|