Skip to content

Commit 12ef5b2

Browse files
authored
ExcludeRestElement: Fix generic assignability with arrays (#1274)
1 parent 3b4ad2e commit 12ef5b2

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

source/exclude-rest-element.d.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type {SplitOnRestElement} from './split-on-rest-element.d.ts';
22
import type {IsArrayReadonly} from './internal/array.d.ts';
33
import type {UnknownArray} from './unknown-array.d.ts';
4+
import type {IfNotAnyOrNever} from './internal/type.d.ts';
45

56
/**
67
Create a tuple with the [`rest`](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types) element removed.
@@ -26,13 +27,14 @@ type T4 = ExcludeRestElement<[number, string]>;
2627
@see {@link SplitOnRestElement}
2728
@category Array
2829
*/
29-
export type ExcludeRestElement<Array_ extends UnknownArray> =
30+
export type ExcludeRestElement<Array_ extends UnknownArray> = IfNotAnyOrNever<Array_,
3031
SplitOnRestElement<Array_> extends infer Result
3132
? Result extends readonly UnknownArray[]
3233
? IsArrayReadonly<Array_> extends true
3334
? Readonly<[...Result[0], ...Result[2]]>
3435
: [...Result[0], ...Result[2]]
35-
: Result
36-
: never;
36+
: never
37+
: never
38+
>;
3739

3840
export {};

test-d/exclude-rest-element.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {expectType} from 'tsd';
2-
import type {ExcludeRestElement} from '../index.d.ts';
2+
import type {ExcludeRestElement, TupleOf, UnknownArray} from '../index.d.ts';
33

44
// Basic static tuples (No rest element)
55
expectType<ExcludeRestElement<[]>>({} as []);
@@ -51,3 +51,14 @@ expectType<ExcludeRestElement<[['a'], ...string[], ['z']]>>({} as [['a'], ['z']]
5151
// Edge: `never` / `any`
5252
expectType<ExcludeRestElement<any>>({} as any);
5353
expectType<ExcludeRestElement<never>>({} as never);
54+
55+
// Long tuples
56+
type FiftyZeroes = TupleOf<50, '0'>;
57+
expectType<ExcludeRestElement<[...FiftyZeroes, ...number[]]>>({} as FiftyZeroes);
58+
59+
type NineHundredNinetyNineZeroes = TupleOf<999, '0'>;
60+
expectType<ExcludeRestElement<[...NineHundredNinetyNineZeroes, ...number[]]>>({} as NineHundredNinetyNineZeroes);
61+
62+
// Generic instantiations
63+
type Assignability<_T extends UnknownArray> = unknown;
64+
type TestAssignability<T extends UnknownArray> = Assignability<ExcludeRestElement<T>>;

test-d/extract-rest-element.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {expectType} from 'tsd';
2-
import type {ExtractRestElement} from '../index.d.ts';
2+
import type {ExtractRestElement, TupleOf} from '../index.d.ts';
33

44
// Leading rest element
55
expectType<ExtractRestElement<[...string[], 1]>>({} as string);
@@ -49,3 +49,10 @@ expectType<ExtractRestElement<[['a'], ...boolean[], ['z']]>>({} as boolean);
4949
// Edge: `never` / `any`
5050
expectType<ExtractRestElement<any>>({} as any);
5151
expectType<ExtractRestElement<never>>({} as never);
52+
53+
// Long tuples
54+
type FiftyZeroes = TupleOf<50, '0'>;
55+
expectType<ExtractRestElement<[...FiftyZeroes, ...number[]]>>({} as number);
56+
57+
type NineHundredNinetyNineZeroes = TupleOf<999, '0'>;
58+
expectType<ExtractRestElement<[...NineHundredNinetyNineZeroes, ...number[]]>>({} as number);

test-d/split-on-rest-element.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {expectType} from 'tsd';
2-
import type {SplitOnRestElement} from '../index.d.ts';
2+
import type {SplitOnRestElement, TupleOf, UnknownArray} from '../index.d.ts';
33

44
// Fixed tuples (No rest element)
55
expectType<SplitOnRestElement<[]>>({} as [[], [], []]);
@@ -53,3 +53,14 @@ expectType<SplitOnRestElement<readonly [1, 2, 3]>>({} as readonly [[1, 2, 3], []
5353
// Edge: `never` / `any`
5454
expectType<SplitOnRestElement<any>>({} as any);
5555
expectType<SplitOnRestElement<never>>({} as never);
56+
57+
// Long tuples
58+
type FiftyZeroes = TupleOf<50, '0'>;
59+
expectType<SplitOnRestElement<[...FiftyZeroes, ...number[], ...FiftyZeroes]>>({} as [FiftyZeroes, number[], FiftyZeroes]);
60+
61+
type FourHundredNinetyNineZeroes = TupleOf<499, '0'>;
62+
expectType<SplitOnRestElement<[...FourHundredNinetyNineZeroes, ...number[], ...FourHundredNinetyNineZeroes]>>({} as [FourHundredNinetyNineZeroes, number[], FourHundredNinetyNineZeroes]);
63+
64+
// Generic instantiations
65+
type Assignability<_T extends UnknownArray> = unknown;
66+
type TestAssignability<T extends UnknownArray> = Assignability<SplitOnRestElement<T>>;

0 commit comments

Comments
 (0)