The problem
Here is my problem, when a class/function has multiple generic types that are not mandatory to specify it often happens that the code looks like this:
const instance = new GenericClass<any, any, number>();
or
const result = genericFunction<string, any, any, number>();
Basically what I am looking for is to avoid specifying all the generic types where I want to leave the default type.
My solution
I had studied this problem a lot, but I am not able to find a solution that doesn't become a problem too.
This is what I come up with after a sleepless night:
First I specify which properties have a generic type and create a utility type GetGeneric which returns the specified type or, in case the type has been omitted for that property, the default type.
type GenericProps = 'input' | 'output';
type AcceptedGenerics = { [Property in GenericProps]: any };
type GetGeneric<T extends Partial<AcceptedGenerics>, Prop extends keyof AcceptedGenerics, TDefault = any> = T extends Pick<AcceptedGenerics, Prop> ? T[Prop] : TDefault
Then here is how I use this method for classes:
class Obj<T extends Partial<AcceptedGenerics>> {
input: GetGeneric<T, 'input', string>
output: GetGeneric<T, 'output', string>
}
const instance = new Obj<{ output: number }>();
/*
instance = {
input: string,
output: number,
}
*/
And here the function version:
function Func<T extends Partial<AcceptedGenerics>>(
input: GetGeneric<T, 'input'>
): GetGeneric<T, 'output', {}> {
return { } as GetGeneric<T, 'output', {}>;
}
const result = Func<{ input: number, output: { prop: string } }>(2);
/*
Func<{ input: number, output: { prop: string } }>() = (input: number) => { prop: string }
*/
I also noticed that in case the extended use of the GetGeneric utility type make the code look messy, it is possible to define all the generic type like so:
function Func<T extends Partial<AcceptedGenerics>, TInput = GetGeneric<T, 'input'>, TOutput = GetGeneric<T, 'output', {}>>(
input: TInput
): TOutput {
return { } as TOutput;
}
But I am not sure if this solution is better or worst.
Conclusions
I am asking you what you think about this solution, if you have any suggestions and if you think this was a problem to solve in the first place.
Top comments (1)
A better way now I think is to use types.
for objects:
for functions: