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?
You could use a function factory to type the function body with tuples as parameters for CreateOps
:
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
})