UNPKG

2.06 kBTypeScriptView Raw
1import type {IfAny} from './if-any';
2import type {IfNever} from './if-never';
3import type {UnknownArray} from './unknown-array';
4
5/**
6@see {@link IsTuple}
7*/
8export type IsTupleOptions = {
9 /**
10 Consider only fixed length arrays as tuples.
11
12 - When set to `true` (default), arrays with rest elements (e.g., `[1, ...number[]]`) are _not_ considered as tuples.
13 - When set to `false`, arrays with at least one non-rest element (e.g., `[1, ...number[]]`) are considered as tuples.
14
15 @default true
16
17 @example
18 ```ts
19 import type {IsTuple} from 'type-fest';
20
21 type Example1 = IsTuple<[number, ...number[]], {fixedLengthOnly: true}>;
22 //=> false
23
24 type Example2 = IsTuple<[number, ...number[]], {fixedLengthOnly: false}>;
25 //=> true
26 ```
27 */
28 fixedLengthOnly?: boolean;
29};
30
31/**
32Returns a boolean for whether the given array is a tuple.
33
34Use-case:
35- If you want to make a conditional branch based on the result of whether an array is a tuple or not.
36
37Note: `IsTuple` returns `boolean` when instantiated with a union of tuple and non-tuple (e.g., `IsTuple<[1, 2] | number[]>`).
38
39@example
40```ts
41import type {IsTuple} from 'type-fest';
42
43type Tuple = IsTuple<[1, 2, 3]>;
44//=> true
45
46type NotTuple = IsTuple<number[]>;
47//=> false
48
49type TupleWithOptionalItems = IsTuple<[1?, 2?]>;
50//=> true
51
52type RestItemsNotAllowed = IsTuple<[1, 2, ...number[]]>;
53//=> false
54
55type RestItemsAllowed = IsTuple<[1, 2, ...number[]], {fixedLengthOnly: false}>;
56//=> true
57```
58
59@see {@link IsTupleOptions}
60
61@category Type Guard
62@category Utilities
63*/
64export type IsTuple<
65 TArray extends UnknownArray,
66 Options extends IsTupleOptions = {fixedLengthOnly: true},
67> =
68 IfAny<TArray, boolean, IfNever<TArray, false,
69 TArray extends unknown // For distributing `TArray`
70 ? number extends TArray['length']
71 ? Options['fixedLengthOnly'] extends false
72 ? IfNever<keyof TArray & `${number}`,
73 TArray extends readonly [...any, any] ? true : false, // To handle cases where a non-rest element follows a rest element, e.g., `[...number[], number]`
74 true>
75 : false
76 : true
77 : false
78 >>;