Generics to work with tuples in TypeScript
- TypeScript ≥ 3.0.0
import { IsFinite } from 'typescript-tuple' type Foo = IsFinite<[0, 1, 2]> // Expect: true const foo: Foo = true type Bar = IsFinite<[0, 1, 2, ...number[]]> // Expect: false const bar: Bar = false type Baz = IsFinite<[0, 1, 2], 'finite', 'infinite'> // Expect: 'finite' const baz: Baz = 'finite'import { SplitInfiniteTuple } from 'typescript-tuple' type Foo = SplitInfiniteTuple<[0, 1, 2, ...number[]]> // Expect: [[0, 1, 2], number[]] type FinitePart = Foo[0] // Expect: [0, 1, 2] type InfinitePart = Foo[1] // Expect: number[] const foo: Foo = [[0, 1, 2], Array<number>()] const finitePart: FinitePart = [0, 1, 2] const infinitePart: InfinitePart = Array<number>()import { First } from 'typescript-tuple' type Foo = First<['a', 'b', 'c']> // Expect: 'a' const foo: Foo = 'a'import { Last } from 'typescript-tuple' type Foo = Last<['a', 'b', 'c']> // Expect: 'c' const foo: Foo = 'c'import { Tail } from 'typescript-tuple' type Foo = Tail<['a', 'b', 'c']> // Expect: ['b', 'c'] const foo: Foo = ['b', 'c']import { FirstIndexEqual } from 'typescript-tuple' type Foo = FirstIndexEqual<'x', ['a', 'x', 'b', 'x']> // Expect: 1 const foo: Foo = 1 type Bar = FirstIndexEqual<'x', ['a', 'b']> // Expect: never type Baz = FirstIndexEqual<'x', ['a', 'b'], 'not found'> // Expect: 'not found' const baz: Baz = 'not found'import { FirstIndexSubset } from 'typescript-tuple' type Foo = FirstIndexSubset<string, [0, 'a', 1, 'b']> // Expect: 1 const foo: Foo = 1 type Bar = FirstIndexSubset<string, [0, 1]> // Expect: never type Baz = FirstIndexSubset<string, [0, 1], 'not found'> // Expect: 'not found' const baz: Baz = 'not found'import { FirstIndexSuperset } from 'typescript-tuple' type Foo = FirstIndexSuperset<'x', [number, string, 0 | 1, 'x' | 'y']> // Expect: 1 const foo: Foo = 1 type Bar = FirstIndexSuperset<'x', [number, 0 | 1]> // Expect: never type Baz = FirstIndexSuperset<'x', [number, 0 | 1], 'not found'> // Expect: 'not found' const baz: Baz = 'not found'import { LastIndexEqual } from 'typescript-tuple' type Foo = LastIndexEqual<'x', ['a', 'x', 'b', 'x']> // Expect: 3 const foo: Foo = 3 type Bar = LastIndexEqual<'x', ['a', 'b']> // Expect: never type Baz = LastIndexEqual<'x', ['a', 'b'], 'not found'> // Expect: 'not found' const baz: Baz = 'not found'import { LastIndexSubset } from 'typescript-tuple' type Foo = LastIndexSubset<string, [0, 'a', 1, 'b']> // Expect: 3 const foo: Foo = 3 type Bar = LastIndexSubset<string, [0, 1]> // Expect: never type Baz = LastIndexSubset<string, [0, 1], 'not found'> // Expect: 'not found' const baz: Baz = 'not found'import { LastIndexSuperset } from 'typescript-tuple' type Foo = LastIndexSuperset<'x', [number, string, 0 | 1, 'x' | 'y']> // Expect: 3 const foo: Foo = 3 type Bar = LastIndexSuperset<'x', [number, 0 | 1]> // Expect: never type Baz = LastIndexSuperset<'x', [number, 0 | 1], 'not found'> // Expect: 'not found' const baz: Baz = 'not found'import { AllIndexesEqual } from 'typescript-tuple' type Foo = AllIndexesEqual<'x', ['a', 'x', 'b', 'x']> // Expect: [1, 3] const foo: Foo = [1, 3] type Bar = AllIndexesEqual<'x', ['a', 'x', 'b', ...'x'[]]> // Expect: [1, ...3[]] const bar: Bar = [1, 3, 3, 3, 3]import { AllIndexesSubset } from 'typescript-tuple' type Foo = AllIndexesSubset<string, [0, 'a', 1, 'b']> // Expect: [1, 3] const foo: Foo = [1, 3] type Bar = AllIndexesSubset<string, [0, 'a', 1, ...'b'[]]> // Expect: [1, ...3[]] const bar: Bar = [1, 3, 3, 3, 3]import { AllIndexesSuper } from 'typescript-tuple' type Foo = AllIndexesSuper<'x', [number, string, 0 | 1, 'x' | 'y']> // Expect: [1, 3] const foo: Foo = [1, 3] type Bar = AllIndexesSuper<'x', [number, string, 0 | 1, ...'x'[]]> // Expect: [1, ...3[]] const bar: Bar = [1, 3, 3, 3, 3]import { Append } from 'typescript-tuple' type Foo = Append<['a', 'b', 'c'], 'x'> // Expect: ['a', 'b', 'c', 'x'] const foo: Foo = ['a', 'b', 'c', 'x']import { Prepend } from 'typescript-tuple' type Foo = Prepend<['a', 'b', 'c'], 'x'> // Expect: ['x', 'a', 'b', 'c'] const foo: Foo = ['x', 'a', 'b', 'c']import { Reverse } from 'typescript-tuple' type Foo = Reverse<['a', 'b', 'c']> // Expect: ['c', 'b', 'a'] const foo: Foo = ['c', 'b', 'a']import { Concat } from 'typescript-tuple' type Foo = Concat<['a', 'b', 'c'], [0, 1, 2]> // Expect ['a', 'b', 'c', 0, 1, 2] const foo: Foo = ['a', 'b', 'c', 0, 1, 2]import { Repeat } from 'typescript-tuple' // Basic type Foo = Repeat<'x', 5> // Expect ['x', 'x', 'x', 'x', 'x'] const foo: Foo = ['x', 'x', 'x', 'x', 'x'] // Using union type Bar = Repeat<'x', 1 | 3 | 4> // Expect ['x'] | ['x', 'x', 'x'] | ['x', 'x', 'x', 'x'] const bar1: Bar = ['x'] const bar3: Bar = ['x', 'x', 'x'] const bar4: Bar = ['x', 'x', 'x', 'x'] // Using ambiguous 'number' type type Baz = Repeat<'x', number> // Expect 'x'[] const baz: Baz = Array<number>()NOTES:
- Due to TypeScript design limitations, using floating point numbers and negative numbers might lead to infinite loop within TSC compiler, avoid doing this.
import { ConcatMultiple } from 'typescript-tuple' type Foo = ConcatMultiple<[[], ['a'], ['b', 'c']]> // Expect ['a', 'b', 'c'] const foo: Foo = ['a', 'b', 'c']import { Drop } from 'typescript-tuple' type Foo = Drop<[0, 1, 2, 3, 4], 2> // Expect [2, 3, 4] const foo: Foo = [2, 3, 4] type Bar = Drop<[0, 1, 2, 3, 4, ...number[]], 2> // Expect [2, 3, 4, ...number[]] const bar: Bar = [2, 3, 4] type Baz = Drop<[0, 1, 2, 3, 4], 10> // Expect [] const baz: Baz = [2, 3, 4] type Qux = Drop<[0, 1, 2, 3, 4, ...number[]], 10> // Expect number[] const qux: Qux = [2, 3, 4]import { SliceStartQuantity } from 'typescript-tuple' type Foo = SliceStartQuantity<[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 2, 4> // Expect [2, 3, 4, 5] const foo: Foo = [2, 3, 4, 5]import { SingleTupleSet } from 'typescript-tuple' type Foo = SingleTupleSet<[0, 1, 2]> // Expect [[0], [1], [2]] const foo: Foo = [[0], [1], [2]] type Bar = SingleTupleSet<'x'[]> // Expect ['x'][] const bar: Bar = Array<['x']>()import { FillTuple } from 'typescript-tuple' type Foo = FillTuple<[0, 1, 2, 3], 'r'> const foo: Foo = ['r', 'r', 'r', 'r']import { CompareLength } from 'typescript-tuple' type Foo = CompareLength<[0, 1, 2], ['a', 'b', 'c']> // Expect: 'equal' const foo: Foo = 'equal' type Bar = CompareLength<[0, 1], ['a', 'b', 'c', 'd']> // Expect: 'shorterLeft' const bar: Bar = 'shorterLeft' type Baz = CompareLength<[0, 1, 2, 3], ['a', 'b']> // Expect: 'shorterRight' const baz: Baz = 'shorterRight'import { SortTwoTuple } from 'typescript-tuple' type Foo = SortTwoTuple<[0, 1], ['a', 'b', 'c', 'd']> // Expect: [[0, 1], ['a', 'b', 'c', 'd']] const foo: Foo = [[0, 1], ['a', 'b', 'c', 'd']] type Bar = SortTwoTuple<[0, 1, 2, 3], ['a', 'b']> // Expect: [['a', 'b'], [0, 1, 2, 3]] const bar: Bar = [['a', 'b'], [0, 1, 2, 3]] type Baz = SortTwoTuple<[0, 1, 2], ['a', 'b', 'c', 'd']> // Expect: [[0, 1, 2], ['a', 'b', 'c']] const baz: Baz = [[0, 1], 3, ['a', 'b', 'c']] type Qux = SortTwoTuple<[0, 1, 2], ['a', 'b', 'c', 'd'], 'EQUAL'> // Expect: 'EQUAL' const qux: Qux = 'EQUAL'import { ShortestTuple } from 'typescript-tuple' type Foo = ShortestTuple<[[0, 1, 2], [false, true], ['a', 'b', 'c', 'd']]> // Expect: [false, true] const foo: Foo = [false, true] type Bar = ShortestTuple<[[0, 1, 2], ['a', 'b', 'c'], ...[false, true][]]> // Expect: [false, true] const bar: Bar = [false, true]import { LongestTuple } from 'typescript-tuple' type Foo = LongestTuple<[[0, 1, 2, 3], [false, true], ['a']]> // Expect: [0, 1, 2, 3] const foo: Foo = [0, 1, 2, 3] type Bar = LongestTuple<[[], [false, true], ...[0, 1, 2][]]> // Expect: [0, 1, 2] const bar: Bar = [0, 1, 2]