How can I infer types based on specified function arguments when the schema is defined within the parent function? I'm attempting to implement a factory pattern but encountering issues with type inference. Here's an example of what I'm trying to achieve:
import { z } from 'zod';
export const makeClient = <T extends string>({
schemas,
}: {
schemas: {
[key in T]: z.ZodSchema;
};
}) => {
type Keys = keyof typeof schemas;
type Values<K extends Keys> = z.infer<typeof schemas[K]>;
return {
async findOne<K extends Keys>({
name,
filter,
}: {
name: K;
filter: Values<K>;
}) {
return { name, filter };
},
};
};
const client = makeClient({
schemas: {
test: z.object({
value: z.number(),
}),
},
});
client.findOne({
name: "test", // this is inferred
filter: {
// not inferred
}
})
I believe it should be possible to achieve type inference in this scenario, but I'm having trouble figuring out how. Any guidance would be appreciated.
I've waited for commenters to respond, but it's been some time now. With the directions from Bergi in comments, I've managed to fix it like below:
import { z } from 'zod';
export const makeClient = <S extends Record<string, z.ZodSchema>>({
schemas,
}: {
schemas: S;
}) => {
return {
async findOne<K extends keyof S>({
name,
filter,
}: {
name: K;
filter: z.infer<S[K]>;
}) {
return { name, filter };
},
};
};
const client = makeClient({
schemas: {
test: z.object({
value: z.number(),
}),
},
});
client.findOne({
name: "test",
filter: {
// now inferred
}
})