Feeling a bit out of my depth here. I need to perform an inference on a generic that includes an optional "parse" function which returns the formatted value [or throws].
They say code speaks louder than words, so let's take a look at the example:
export type RouteDefInput<TInput = unknown> = {
parse: (input: unknown) => TInput;
};
export type RouteDefResolver<
TContext = unknown,
TInput = unknown,
TOutput = unknown
> = (opts: { ctx: TContext; input: TInput }) => Promise<TOutput> | TOutput;
export type RouteDef<
TContext = unknown,
TInput = unknown,
TOutput = unknown
> = {
input?: RouteDefInput<TInput>;
resolve: RouteDefResolver<TContext, TInput, TOutput>;
};
export type inferRouteInput<
TRoute extends RouteDef<any, any, any>
> = TRoute['input'] extends RouteDefInput<any>
? ReturnType<TRoute['input']['parse']>
: undefined;
const context = {};
function createRoute<TInput, TOutput>(
route: RouteDef<typeof context, TInput, TOutput>
) {
return route;
}
function stringParser(input: unknown): string {
if (typeof input === 'string') {
return input;
}
throw new Error('not a string');
}
const myRoute1 = createRoute({
input: {
parse: stringParser,
},
resolve({ input }) {
return {
output: input,
};
},
});
const myRoute2 = createRoute({
resolve({ input }) {
return {
output: input,
};
},
});
// this should render MyRouteInput1 as "string"
type MyRouteInput1 = inferRouteInput<typeof myRoute1>;
// this should render MyRouteInput2 as "undefined" (works)
type MyRouteInput2 = inferRouteInput<typeof myRoute2>;
Can anyone help me figure out how to properly get the inferRouteInput
to work in both cases?
I've been struggling with this for quite a while - you can test it out yourself in the TypeScript playground: TypeScript Playground
Your assistance is greatly appreciated! 🙏
If you have any recommendations for further reading on this topic or on TypeScript generics in general, please feel free to share as I'm having trouble finding reliable sources.