-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inconsistent typing of parse
result when using generic schema types
#2153
Comments
I can get the correct types if I do: return schema.parse(thing) as z.infer<TSchema> But shouldn't we be able to have the return type inferred without having to do that? |
As a better example let's say we're returning the result of Taking a look at Matt's zod-fetch I saw a bit of type magic he was doing: https://github.com/mattpocock/zod-fetch/blob/28b3c5a33769243a350d921eb2dae7bd08e8bf1b/src/createZodFetcher.ts#L10-L12 The thing is, that then works beautifully if you're just calling Is it not possible to have the best of both worlds? A generic Zod type that allows the return type to be inferred? import { z } from 'zod'
const zSchema = z.object({
name: z.string()
})
export type Schema<TSafeParseData> = {
safeParse: (data: unknown) => TSafeParseData;
};
function validate<TSafeParseData>(
thing: any,
schema: Schema<TSafeParseData>,
) {
return schema.safeParse(thing)
}
// typed as:
// z.SafeParseReturnType<{
// name: string;
// }, {
// name: string;
// }>
const result = validate({ name: "zoddy" }, zSchema)
function validate2<TSafeParseData>(
thing: any,
schema: Schema<TSafeParseData>,
) {
const nested = z.object({
// Type 'Schema<TSafeParseData>' is missing the following properties from type 'ZodType<any, any, any>': _type, _output, _input, _def,
nested: schema
})
return nested.parse(thing)
}
const result2 = validate2({ nested: { name: "zoddy" }}, zSchema) |
seems like a bug, not sure how to fix it |
You need to do this: function validate<TSchema extends z.ZodTypeAny>(thing: any, schema: TSchema) {
return schema.parse(thing) as z.infer<TSchema>;
} The result of Basically TypeScript will stop propagating the generic at a certain point and try to resolve everything to "real" types. Put another way, don't rely on inferred return types with generic functions. |
@colinhacks is there an equivalent for the return value of |
This approach seemed promising.. the return value gets inferred automatically when returning import { z } from 'zod'
const zSchema = z.object({
name: z.string()
})
type SafeParseReturn = z.SafeParseReturnType<unknown, unknown>
interface Schema<TData, TSafeParseData extends SafeParseReturn> extends z.ZodTypeAny {
parse: (data: unknown) => TData;
safeParse: (data: unknown) => TSafeParseData;
};
function validate<TSafeParseData extends SafeParseReturn>(
thing: unknown,
schema: Schema<any, TSafeParseData>,
) {
return schema.safeParse(thing)
}
// inferred as:
// z.SafeParseReturnType<{
// name: string;
// }, {
// name: string;
// }>
const result = validate({ name: "zoddy" }, zSchema)
function validate2<TSafeParseData extends SafeParseReturn>(
thing: any,
schema: Schema<any, TSafeParseData>,
) {
const nested = z.object({
nested: schema
})
return nested.safeParse(thing)
}
// inferred as:
// z.SafeParseReturnType<{
// nested?: any;
// }, {
// nested?: any;
// }>
const result2 = validate2({ nested: { name: "zoddy" }}, zSchema) |
function validate<TSchema extends z.ZodTypeAny>(thing: any, schema: TSchema) {
return schema.parse(thing) as ReturnType<TSchema["safeParse"]>;
} |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Still relevant! |
Against recommended solutions I was able to get full type inference using the following pattern: function validate<Output, Input>(thing: any, schema: ZodType<Output, ZodTypeDef, Input>) {
return schema.parse(thing);
}
// usage
const res = validate(thing, schema);
//^ should be inferred correctly as the output of your schema |
Following on from #2146
I'm still having issues getting return values of functions that accept generic schemas to work right.
It now works perfectly if I'm nesting the schema inside a new schema. But if I'm simply using the schema as-is, the result type doesn't get inferred and gets typed as
any
.https://tsplay.dev/mZ1zJN
The text was updated successfully, but these errors were encountered: