typescripttypescript-generics

Infinite number of generic pairs


I have a function that has 1-3 options where each option consists of generic types. I want to change this functionality so that it can take from 0-infinite amount of these pairs:

type CreateOpts<Type extends string, T> = {
  type: Type;
  things: Array<T>
};

type MyOptions<
  TType1 extends string = string,
  T1 = any,
  TType2 extends string = string,
  T2 = any,
  TType3 extends string = string,
  T3 = any
> = {
  opts: Readonly<
  | [
       CreateOpts<TType1, T1>,
    ]
  | [
       CreateOpts<TType1, T1>,
       CreateOpts<TType2, T2>,
    ]
  | [
       CreateOpts<TType1, T1>,
       CreateOpts<TType2, T2>,
       CreateOpts<TType3, T3>,
    ]
  >;
};

function myFunc<TType1 extends string, T1, TType2 extends string, T2, TType3 extends string, T3>(
  options: MyOptions<TType1, T1, TType2, T2, TType3, T3>
) {
  for(const thing of options.things) {
    console.log(things);
  }
}

How can I make it so I can pass there any number of "tuples" with generics?


Solution

  • You could use a function factory to type the function body with tuples as parameters for CreateOps:

    Playground

    type CreateOpts<Type extends string, T> = {
      type: Type;
      things: Array<T>
    };
    
    type OptionParams<Type extends string, T> = [Type, T];
    
    function myFuncMaker<
      P extends OptionParams<string, any>  
    >(
      cb: (option: Readonly<P extends OptionParams<infer A, infer B> ? CreateOpts<A, B> : never>) => void
    ){
      return cb;
    }
    
    const myFunc1 = myFuncMaker<['type', number] | ['type2', string]>(option => {
    
      if(option.type === 'type') {
        for(const thing of option.things){
          console.log(thing); // number
        }
      }
    
    });
    
    myFunc1({
      type: 'type',
      things: [1,2,3]
    })
    
    myFunc1({
      type: 'type2',
      things:['asdf', 'asdf', 'asdf']
    })
    
    myFunc1({
      type: 'type2',
      things:[1, 2, 3] // error
    })