Skip to content

Commit dfbefad

Browse files
som-smbenzaria
andauthored
Add ArrayReverse type (#1266)
Co-authored-by: benz <benzaria@users.noreply.github.com>
1 parent b3ecd07 commit dfbefad

File tree

7 files changed

+390
-5
lines changed

7 files changed

+390
-5
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,4 @@ jobs:
4242
node-version: 24
4343
- run: npm install
4444
- run: npm install typescript@${{ matrix.typescript-version }}
45-
- run: NODE_OPTIONS="--max-old-space-size=5120" npx tsc
45+
- run: NODE_OPTIONS="--max-old-space-size=6144" npx tsc

.github/workflows/ts-canary.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ jobs:
2323
- run: npm install typescript@${{ matrix.typescript-version }}
2424
- name: show installed typescript version
2525
run: npm list typescript --depth=0
26-
- run: NODE_OPTIONS="--max-old-space-size=5120" npx tsc
26+
- run: NODE_OPTIONS="--max-old-space-size=6144" npx tsc

index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ export type {IsOptional} from './source/is-optional.d.ts';
164164
export type {IsNullable} from './source/is-nullable.d.ts';
165165
export type {TupleOf} from './source/tuple-of.d.ts';
166166
export type {ExclusifyUnion} from './source/exclusify-union.d.ts';
167+
export type {ArrayReverse} from './source/array-reverse.d.ts';
167168

168169
// Template literal types
169170
export type {CamelCase, CamelCaseOptions} from './source/camel-case.d.ts';

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
"node": ">=20"
2626
},
2727
"scripts": {
28-
"test:tsc": "node --max-old-space-size=5120 ./node_modules/.bin/tsc",
29-
"test:tsd": "tsd",
30-
"test:xo": "xo",
28+
"test:tsc": "node --max-old-space-size=6144 ./node_modules/.bin/tsc",
29+
"test:tsd": "node --max-old-space-size=6144 ./node_modules/.bin/tsd",
30+
"test:xo": "node --max-old-space-size=6144 ./node_modules/.bin/xo",
3131
"test:linter": "node --test",
3232
"test": "run-p test:*"
3333
},

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ Click the type names for complete docs.
263263
- [`SplitOnRestElement`](source/split-on-rest-element.d.ts) - Splits an array into three parts, where the first contains all elements before the rest element, the second is the [`rest`](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types) element itself, and the third contains all elements after the rest element.
264264
- [`ExtractRestElement`](source/extract-rest-element.d.ts) - Extract the [`rest`](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types) element type from an array.
265265
- [`ExcludeRestElement`](source/exclude-rest-element.d.ts) - Create a tuple with the [`rest`](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types) element removed.
266+
- [`ArrayReverse`](source/array-reverse.d.ts) - Reverse the order of elements in a tuple type.
266267

267268
### Numeric
268269

source/array-reverse.d.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import type {If} from './if.d.ts';
2+
import type {IsArrayReadonly} from './internal/array.d.ts';
3+
import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled} from './internal/type.d.ts';
4+
import type {IsOptionalKeyOf} from './is-optional-key-of.d.ts';
5+
import type {UnknownArray} from './unknown-array.d.ts';
6+
7+
/**
8+
Reverse the order of elements in a tuple type.
9+
10+
@example
11+
```ts
12+
import type {ArrayReverse} from 'type-fest';
13+
14+
type A = ArrayReverse<[string, number, boolean]>;
15+
//=> [boolean, number, string]
16+
17+
type B = ArrayReverse<readonly [string, number, ...boolean[]]>;
18+
//=> readonly [...boolean[], number, string]
19+
20+
type C = ArrayReverse<['foo', 'bar'] | readonly [1, 2, 3]>;
21+
//=> ["bar", "foo"] | readonly [3, 2, 1]
22+
23+
type D = ArrayReverse<string[]>;
24+
//=> string[]
25+
26+
type E = ArrayReverse<[]>;
27+
//=> []
28+
```
29+
30+
Note: If the tuple contains optional elements, the result will be a union of tuples, refer to the examples below:
31+
32+
@example
33+
```ts
34+
import type {ArrayReverse} from 'type-fest';
35+
36+
type A = ArrayReverse<[string, number, boolean?]>;
37+
//=> [boolean, number, string] | [number, string]
38+
39+
type B = ArrayReverse<[string, number?, boolean?]>;
40+
//=> [boolean, number, string] | [number, string] | [string]
41+
42+
type C = ArrayReverse<[string?, number?, boolean?]>;
43+
//=> [boolean, number, string] | [number, string] | [string] | []
44+
45+
type D = ArrayReverse<[string, number?, ...boolean[]]>;
46+
//=> [...boolean[], number, string] | [string]
47+
48+
type E = ArrayReverse<[string?, number?, ...boolean[]]>;
49+
//=> [...boolean[], number, string] | [string] | []
50+
```
51+
52+
@category Array
53+
*/
54+
export type ArrayReverse<TArray extends UnknownArray> = IfNotAnyOrNever<TArray,
55+
TArray extends unknown // For distributing `TArray`
56+
? _ArrayReverse<TArray> extends infer Result
57+
? If<IsArrayReadonly<TArray>, Readonly<Result>, Result>
58+
: never // Should never happen
59+
: never>; // Should never happen
60+
61+
type _ArrayReverse<
62+
TArray extends UnknownArray,
63+
BeforeRestAcc extends UnknownArray = [],
64+
AfterRestAcc extends UnknownArray = [],
65+
Result extends UnknownArray = never,
66+
> =
67+
keyof TArray & `${number}` extends never
68+
// Enters this branch, if `TArray` is empty (e.g., `[]`),
69+
// or `TArray` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
70+
? TArray extends readonly [...infer Rest, infer Last]
71+
? _ArrayReverse<Rest, BeforeRestAcc, [...AfterRestAcc, Last], Result> // Accumulate elements that are present after the rest element in reverse order.
72+
: Result | [...AfterRestAcc, ...TArray, ...BeforeRestAcc] // Add the rest element between the accumulated elements.
73+
: TArray extends readonly [(infer First)?, ...infer Rest]
74+
? IsOptionalKeyOf<TArray, '0'> extends true
75+
? _ArrayReverse<
76+
Rest,
77+
[First | (If<IsExactOptionalPropertyTypesEnabled, never, undefined>), ...BeforeRestAcc], // Add `| undefined` for optional elements, if `exactOptionalPropertyTypes` is disabled.
78+
AfterRestAcc,
79+
Result | BeforeRestAcc
80+
>
81+
: _ArrayReverse<Rest, [First, ...BeforeRestAcc], AfterRestAcc, Result>
82+
: never; // Should never happen, since `readonly [(infer First)?, ...infer Rest]` is a top-type for arrays.
83+
84+
export {};

0 commit comments

Comments
 (0)