diff --git a/source/array-slice.d.ts b/source/array-slice.d.ts index 045d41f3..da684932 100644 --- a/source/array-slice.d.ts +++ b/source/array-slice.d.ts @@ -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> extends true - ? Array_ - : number extends Array_['length'] - ? VariableLengthArraySliceHelper - : ArraySliceHelper extends true ? 0 : Start, IsEqual extends true ? Array_['length'] : End> + ? IsNever extends true + ? IsNever extends true + ? _ArraySlice + : End extends unknown // To distribute `End` + ? _ArraySlice + : never // Never happens + : IsNever extends true + ? Start extends unknown // To distribute `Start` + ? _ArraySlice + : never // Never happens + : Start extends unknown // To distribute `Start` + ? End extends unknown // To distribute `End` + ? _ArraySlice + : 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> extends true + ? Array_ + : number extends Array_['length'] + ? VariableLengthArraySliceHelper + : ArraySliceHelper extends true ? 0 : Start, IsEqual extends true ? Array_['length'] : End>; + type VariableLengthArraySliceHelper< Array_ extends readonly unknown[], Start extends number, diff --git a/source/string-slice.d.ts b/source/string-slice.d.ts index cfb2a8b4..e125a99e 100644 --- a/source/string-slice.d.ts +++ b/source/string-slice.d.ts @@ -28,8 +28,8 @@ StringSlice<'abcde', -2, -1>; */ export type StringSlice< S extends string, - Start extends number = 0, - End extends number = StringToArray['length'], + Start extends number = never, + End extends number = never, > = string extends S ? string : ArraySlice, Start, End> extends infer R extends readonly string[] diff --git a/test-d/array-slice.ts b/test-d/array-slice.ts index 5bc4b23a..146bf62c 100644 --- a/test-d/array-slice.ts +++ b/test-d/array-slice.ts @@ -38,3 +38,40 @@ expectType>([1, 2, 3, ...(null! as s expectType>([2, 3, ...(null! as string[]), 4, 5]); expectType>([...(null! as string[]), 4, 5]); expectType>([...(null! as string[]), 4, 5]); + +// Unions +// Array is union +expectType>({} as [0, 1, 2] | ['a', 'b', 'c', 'd']); // Positive start, no end +expectType>({} as [1, 2] | ['c', 'd']); // Negative start, no end +expectType>({} as [0, 1] | ['a', 'b']); // Positive start, positive end +expectType>({} as [1] | ['c']); // Negative start, negative end +expectType>({} as [0, 1] | ['b']); // Negative start, positive end +expectType>({} as [1] | ['b', 'c']); // Positive start, negative end + +// Start is union +expectType>({} as [1, 2, 3] | [2, 3]); // Positive/Negative start, no end +expectType>({} as [2] | [1, 2]); // Positive/Negative start, positive end +expectType>({} as [2] | [0, 1, 2]); // Positive/Negative start, negative end + +// End is union +expectType>({} as [0] | [0, 1]); // Positive start, positive/negative end +expectType>({} as [] | [2]); // Negative start, positive/negative end + +// Array and start are unions +expectType>({} as [1, 2] | [2] | ['b', 'c', 'd'] | ['d']); // Positive/Negative start, no end +expectType>({} as [1] | ['b'] | []); // Positive/Negative start, positive end +expectType>({} as [0, 1] | [1] | ['a', 'b', 'c'] | ['c']); // Positive/Negative start, negative end + +// Array and end are unions +expectType>({} as [2] | [] | ['c']); // Positive start, positive/negative end +expectType>({} as [0, 1, 2] | [0] | ['b', 'c'] | ['b']); // Negative start, positive/negative end + +// Start and end are unions +expectType>( // Positive/Negative start, positive/negative end + {} as [0, 1] | [0, 1, 2] | [] | [1] | [1, 2], +); + +// Array, start and end are unions +expectType>( // 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'], +); diff --git a/test-d/string-slice.ts b/test-d/string-slice.ts index fffb9428..20a609f0 100644 --- a/test-d/string-slice.ts +++ b/test-d/string-slice.ts @@ -15,3 +15,40 @@ expectType>(''); expectType>(null! as string); expectType>(null! as string); expectType>(null! as string); + +// Unions +// String is union +expectType>({} as '012' | 'abcd'); // Positive start, no end +expectType>({} as '12' | 'cd'); // Negative start, no end +expectType>({} as '01' | 'ab'); // Positive start, positive end +expectType>({} as '1' | 'c'); // Negative start, negative end +expectType>({} as '01' | 'b'); // Negative start, positive end +expectType>({} as '1' | 'bc'); // Positive start, negative end + +// Start is union +expectType>({} as '123' | '23'); // Positive/Negative start, no end +expectType>({} as '2' | '12'); // Positive/Negative start, positive end +expectType>({} as '2' | '012'); // Positive/Negative start, negative end + +// End is union +expectType>({} as '0' | '01'); // Positive start, positive/negative end +expectType>({} as '' | '2'); // Negative start, positive/negative end + +// Array and start are unions +expectType>({} as '12' | '2' | 'bcd' | 'd'); // Positive/Negative start, no end +expectType>({} as '1' | 'b' | ''); // Positive/Negative start, positive end +expectType>({} as '01' | '1' | 'abc' | 'c'); // Positive/Negative start, negative end + +// Array and end are unions +expectType>({} as '2' | '' | 'c'); // Positive start, positive/negative end +expectType>({} as '012' | '0' | 'bc' | 'b'); // Negative start, positive/negative end + +// Start and end are unions +expectType>( // Positive/Negative start, positive/negative end + {} as '01' | '012' | '' | '1' | '12', +); + +// Array, start and end are unions +expectType>( // Positive/Negative start, positive/negative end + {} as '1' | '12' | '01' | '012' | 'abcd' | 'abc' | 'bc' | 'bcd', +);