mirror of
https://github.com/sindresorhus/type-fest.git
synced 2025-12-08 19:25:05 +00:00
ArraySlice / StringSlice: Fix behavior with unions (#1291)
This commit is contained in:
parent
c300548e0f
commit
133258b8eb
31
source/array-slice.d.ts
vendored
31
source/array-slice.d.ts
vendored
@ -7,6 +7,7 @@ import type {Not, TupleMin} from './internal/index.d.ts';
|
||||
import type {IsEqual} from './is-equal.d.ts';
|
||||
import type {And} from './and.d.ts';
|
||||
import type {ArraySplice} from './array-splice.d.ts';
|
||||
import type {IsNever} from './is-never.d.ts';
|
||||
|
||||
/**
|
||||
Returns an array slice of a given range, just like `Array#slice()`.
|
||||
@ -60,13 +61,33 @@ export type ArraySlice<
|
||||
Start extends number = never,
|
||||
End extends number = never,
|
||||
> = Array_ extends unknown // To distributive type
|
||||
? And<IsEqual<Start, never>, IsEqual<End, never>> extends true
|
||||
? Array_
|
||||
: number extends Array_['length']
|
||||
? VariableLengthArraySliceHelper<Array_, Start, End>
|
||||
: ArraySliceHelper<Array_, IsEqual<Start, never> extends true ? 0 : Start, IsEqual<End, never> extends true ? Array_['length'] : End>
|
||||
? IsNever<Start> extends true
|
||||
? IsNever<End> extends true
|
||||
? _ArraySlice<Array_, Start, End>
|
||||
: End extends unknown // To distribute `End`
|
||||
? _ArraySlice<Array_, Start, End>
|
||||
: never // Never happens
|
||||
: IsNever<End> extends true
|
||||
? Start extends unknown // To distribute `Start`
|
||||
? _ArraySlice<Array_, Start, End>
|
||||
: never // Never happens
|
||||
: Start extends unknown // To distribute `Start`
|
||||
? End extends unknown // To distribute `End`
|
||||
? _ArraySlice<Array_, Start, End>
|
||||
: never // Never happens
|
||||
: never // Never happens
|
||||
: never; // Never happens
|
||||
|
||||
type _ArraySlice<
|
||||
Array_ extends readonly unknown[],
|
||||
Start extends number = 0,
|
||||
End extends number = Array_['length'],
|
||||
> = And<IsEqual<Start, never>, IsEqual<End, never>> extends true
|
||||
? Array_
|
||||
: number extends Array_['length']
|
||||
? VariableLengthArraySliceHelper<Array_, Start, End>
|
||||
: ArraySliceHelper<Array_, IsEqual<Start, never> extends true ? 0 : Start, IsEqual<End, never> extends true ? Array_['length'] : End>;
|
||||
|
||||
type VariableLengthArraySliceHelper<
|
||||
Array_ extends readonly unknown[],
|
||||
Start extends number,
|
||||
|
||||
4
source/string-slice.d.ts
vendored
4
source/string-slice.d.ts
vendored
@ -28,8 +28,8 @@ StringSlice<'abcde', -2, -1>;
|
||||
*/
|
||||
export type StringSlice<
|
||||
S extends string,
|
||||
Start extends number = 0,
|
||||
End extends number = StringToArray<S>['length'],
|
||||
Start extends number = never,
|
||||
End extends number = never,
|
||||
> = string extends S
|
||||
? string
|
||||
: ArraySlice<StringToArray<S>, Start, End> extends infer R extends readonly string[]
|
||||
|
||||
@ -38,3 +38,40 @@ expectType<ArraySlice<[1, 2, 3, ...string[], 4, 5], 0>>([1, 2, 3, ...(null! as s
|
||||
expectType<ArraySlice<[1, 2, 3, ...string[], 4, 5], 1>>([2, 3, ...(null! as string[]), 4, 5]);
|
||||
expectType<ArraySlice<[1, 2, 3, ...string[], 4, 5], 3>>([...(null! as string[]), 4, 5]);
|
||||
expectType<ArraySlice<[1, 2, 3, ...string[], 4, 5], 10>>([...(null! as string[]), 4, 5]);
|
||||
|
||||
// Unions
|
||||
// Array is union
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], 0>>({} as [0, 1, 2] | ['a', 'b', 'c', 'd']); // Positive start, no end
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], -2>>({} as [1, 2] | ['c', 'd']); // Negative start, no end
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], 0, 2>>({} as [0, 1] | ['a', 'b']); // Positive start, positive end
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], -2, -1>>({} as [1] | ['c']); // Negative start, negative end
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], -3, 2>>({} as [0, 1] | ['b']); // Negative start, positive end
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], 1, -1>>({} as [1] | ['b', 'c']); // Positive start, negative end
|
||||
|
||||
// Start is union
|
||||
expectType<ArraySlice<[0, 1, 2, 3], 1 | -2>>({} as [1, 2, 3] | [2, 3]); // Positive/Negative start, no end
|
||||
expectType<ArraySlice<[0, 1, 2, 3], 2 | -3, 3>>({} as [2] | [1, 2]); // Positive/Negative start, positive end
|
||||
expectType<ArraySlice<[0, 1, 2, 3], 0 | -2, -1>>({} as [2] | [0, 1, 2]); // Positive/Negative start, negative end
|
||||
|
||||
// End is union
|
||||
expectType<ArraySlice<[0, 1, 2, 3], 0, 1 | -2>>({} as [0] | [0, 1]); // Positive start, positive/negative end
|
||||
expectType<ArraySlice<[0, 1, 2, 3], -2, 2 | -1>>({} as [] | [2]); // Negative start, positive/negative end
|
||||
|
||||
// Array and start are unions
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], 1 | -1>>({} as [1, 2] | [2] | ['b', 'c', 'd'] | ['d']); // Positive/Negative start, no end
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], 1 | -2, 2>>({} as [1] | ['b'] | []); // Positive/Negative start, positive end
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], 0 | -2, -1>>({} as [0, 1] | [1] | ['a', 'b', 'c'] | ['c']); // Positive/Negative start, negative end
|
||||
|
||||
// Array and end are unions
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], 2, 3 | -1>>({} as [2] | [] | ['c']); // Positive start, positive/negative end
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], -3, 3 | -2>>({} as [0, 1, 2] | [0] | ['b', 'c'] | ['b']); // Negative start, positive/negative end
|
||||
|
||||
// Start and end are unions
|
||||
expectType<ArraySlice<[0, 1, 2, 3], -5 | 0 | 1, -2 | 0 | 3>>( // Positive/Negative start, positive/negative end
|
||||
{} as [0, 1] | [0, 1, 2] | [] | [1] | [1, 2],
|
||||
);
|
||||
|
||||
// Array, start and end are unions
|
||||
expectType<ArraySlice<[0, 1, 2] | ['a', 'b', 'c', 'd'], 1 | -4, 4 | -1>>( // Positive/Negative start, positive/negative end
|
||||
{} as [1] | [1, 2] | [0, 1] | [0, 1, 2] | ['a', 'b', 'c', 'd'] | ['a', 'b', 'c'] | ['b', 'c'] | ['b', 'c', 'd'],
|
||||
);
|
||||
|
||||
@ -15,3 +15,40 @@ expectType<StringSlice<'abcde', 100, 1>>('');
|
||||
expectType<StringSlice<string>>(null! as string);
|
||||
expectType<StringSlice<string, 1>>(null! as string);
|
||||
expectType<StringSlice<string, 1, 2>>(null! as string);
|
||||
|
||||
// Unions
|
||||
// String is union
|
||||
expectType<StringSlice<'012' | 'abcd', 0>>({} as '012' | 'abcd'); // Positive start, no end
|
||||
expectType<StringSlice<'012' | 'abcd', -2>>({} as '12' | 'cd'); // Negative start, no end
|
||||
expectType<StringSlice<'012' | 'abcd', 0, 2>>({} as '01' | 'ab'); // Positive start, positive end
|
||||
expectType<StringSlice<'012' | 'abcd', -2, -1>>({} as '1' | 'c'); // Negative start, negative end
|
||||
expectType<StringSlice<'012' | 'abcd', -3, 2>>({} as '01' | 'b'); // Negative start, positive end
|
||||
expectType<StringSlice<'012' | 'abcd', 1, -1>>({} as '1' | 'bc'); // Positive start, negative end
|
||||
|
||||
// Start is union
|
||||
expectType<StringSlice<'0123', 1 | -2>>({} as '123' | '23'); // Positive/Negative start, no end
|
||||
expectType<StringSlice<'0123', 2 | -3, 3>>({} as '2' | '12'); // Positive/Negative start, positive end
|
||||
expectType<StringSlice<'0123', 0 | -2, -1>>({} as '2' | '012'); // Positive/Negative start, negative end
|
||||
|
||||
// End is union
|
||||
expectType<StringSlice<'0123', 0, 1 | -2>>({} as '0' | '01'); // Positive start, positive/negative end
|
||||
expectType<StringSlice<'0123', -2, 2 | -1>>({} as '' | '2'); // Negative start, positive/negative end
|
||||
|
||||
// Array and start are unions
|
||||
expectType<StringSlice<'012' | 'abcd', 1 | -1>>({} as '12' | '2' | 'bcd' | 'd'); // Positive/Negative start, no end
|
||||
expectType<StringSlice<'012' | 'abcd', 1 | -2, 2>>({} as '1' | 'b' | ''); // Positive/Negative start, positive end
|
||||
expectType<StringSlice<'012' | 'abcd', 0 | -2, -1>>({} as '01' | '1' | 'abc' | 'c'); // Positive/Negative start, negative end
|
||||
|
||||
// Array and end are unions
|
||||
expectType<StringSlice<'012' | 'abcd', 2, 3 | -1>>({} as '2' | '' | 'c'); // Positive start, positive/negative end
|
||||
expectType<StringSlice<'012' | 'abcd', -3, 3 | -2>>({} as '012' | '0' | 'bc' | 'b'); // Negative start, positive/negative end
|
||||
|
||||
// Start and end are unions
|
||||
expectType<StringSlice<'0123', -5 | 0 | 1, -2 | 0 | 3>>( // Positive/Negative start, positive/negative end
|
||||
{} as '01' | '012' | '' | '1' | '12',
|
||||
);
|
||||
|
||||
// Array, start and end are unions
|
||||
expectType<StringSlice<'012' | 'abcd', 1 | -4, 4 | -1>>( // Positive/Negative start, positive/negative end
|
||||
{} as '1' | '12' | '01' | '012' | 'abcd' | 'abc' | 'bc' | 'bcd',
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user