0

TLDR:

something like:

type type4= 5-1 //type 4
// also ok
type type4= '5'-'1' // type '4'

how can I achieve something similar?

details

I want to build a generic function type that receives number literal (or string literal) and returns unions of numbers until '0'. for example if '3' was passed then the return would be '0'|'1'|'2'. lets call this generic RangeUnion.

type Union01 = RangeUnion<'1'> // should be '0'|'1'  - RangeUnion should be implemented

Why?

this is only for reference and not necessary to understand in order to answer my specific question on top. if you don't have an answer to the question above, maybe you can help with some idea for different implementation.

I'm building developers API for react component and I want to create sophisticated type inferring using typescript. without going to much into details: I have array of types when each item in the array depends on prior items in the array. i want to create intersection of the types until the given type in the array, for example:

// utilities
type GetIndex<A extends any[], T> = {
  [K in keyof A]: A[K] extends T ? K : never;
}[number];
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;

// actual
type Arr = [{ type0: any }, { type1: any }, { type2: any },]
type Type1 = GetIndex<Arr, { type1: any }> // type is '1' - good
type Union01 = RangeUnion<Type1> // should be 0|1 - RangeUnion should be implemented
type DesiredType = UnionToIntersection<Arr[Union01]> //type is { type0: any } & { type1: any }

Playground

Eliav Louski
  • 3,593
  • 2
  • 28
  • 52

1 Answers1

0

thank you very much @robert and @captain-yossarian your answers help wrote the complete solution I was needed, I did slight modifications:

// utils
type GetIndex<Arr extends Array<any>, T> = Arr extends [...infer Tail, infer Last]
  ? Last extends T
    ? Tail["length"]
    : GetIndex<Tail, T>
  : never;
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
type BuildTuple<L extends number, T extends any[] = []> = T extends { length: L } ? T : BuildTuple<L, [...T, any]>;
type RangeUnion<N extends number, Result extends Array<unknown> = []> = Result["length"] extends N
  ? Result[number]
  : RangeUnion<N, [...Result, Result["length"]]>;

// actual
type Arr = [{ type0: any }, { type1: any }, { type2: any }];
type Type2 = GetIndex<Arr, { type2: any }>; 
type Union01 = RangeUnion<Type2>; 
type DesiredType = UnionToIntersection<Arr[Union01]>; //type is { type0: any } & { type1: any }
// works!

anyone needing explicitly use addition or subtraction of literal number types in typescript can see it in the great article @Roberto Zvjerković commented

Eliav Louski
  • 3,593
  • 2
  • 28
  • 52