question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support parametrisable schemas

See original GitHub issue

It would be cool to be able to do something like this:

export type Foo<T> = {
  name: string
  value: T
}

const fooSchema = <T>(valueSchema: z.ZodSchema<T>): z.ZodSchema<Foo<T>> => z.object({
  name: z.string(),
  value: valueSchema
})

(In fact it would be even cooler to be able to use z.infer on the ReturnType<typeof fooSchema>, but TypeScript is not yet capable of this – see https://github.com/microsoft/TypeScript/issues/40542)

The above code produces the following compile error, which I have to be honest, is beyond my understanding:

error TS2322: Type 'ZodObject<{ name: ZodString; value: ZodType<T, ZodTypeDef>; }, { strict: true; }, { [k in keyof ({ [k in undefined extends T ? "value" : never]?: { name: string; value: T; }[k] | undefined; } & { [k in Exclude<...> | Exclude<...>]: { ...; }[k]; })]: ({ [k in undefined extends T ? "value" : never]?: { ...; }[k] | und...' is not assignable to type 'ZodType<Foo<T>, ZodTypeDef>'.
  Types of property '_type' are incompatible.
    Type '{ [k in keyof ({ [k in undefined extends T ? "value" : never]?: { name: string; value: T; }[k] | undefined; } & { [k in Exclude<"name", undefined extends T ? "value" : never> | Exclude<...>]: { ...; }[k]; })]: ({ [k in undefined extends T ? "value" : never]?: { ...; }[k] | undefined; } & { [k in Exclude<...> | Exclu...' is missing the following properties from type 'Foo<T>': name, value

45 const fooSchema = <T>(valueSchema: z.ZodSchema<T>): z.ZodSchema<Foo<T>> => z.object({
                                                                              ~~~~~~~~~~
46   name: z.string(),
   ~~~~~~~~~~~~~~~~~~~
47   value: valueSchema
   ~~~~~~~~~~~~~~~~~~~~
48 })
   ~~

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
colinhackscommented, Sep 15, 2020

This is possible! But generics are finicky as hell. Here’s how to do it:

export type Foo<T> = {
  name: string;
  value: T;
};

const fooSchema = <T extends z.ZodTypeAny>(
  valueSchema: T,
): z.ZodObject<{ name: z.ZodString; value: T }> =>
  z.object({
    name: z.string(),
    value: valueSchema,
  });

const asdf = fooSchema(z.string());

Your issue was having your generic T infer the TS type of the schema instead of the schema itself. That’s necessary in order for TypeScript to properly infer the subclass of the ZodSchema instance that you pass in. Otherwise everything will be inferred as a ZodSchema instance without any subclass-specific methods (though the inferred type will be correct!).

Btw your code works fine if you get rid of the return type annotation. TS can infer the output type correctly.

export type Foo<T> = {
  name: string
  value: T
}

const fooSchema = <T>(valueSchema: z.ZodSchema<T>) => z.object({
  name: z.string(),
  value: valueSchema
})

I’m planning to add a guide to the README detailing how to build generic methods on top of Zod - should have done it a long time ago!

1reaction
colinhackscommented, Sep 16, 2020

The reason this is hard is because it’s the opposite of how Zod works. Normally it infer static type from validator structure, you want to “infer” validator structure from a static type. I talk about this concept a bit here: https://github.com/vriad/zod/issues/53#issuecomment-655937376

As that comment mentions, I published a separate npm module tozod that I’ve published but it should be considered a proof-of-concept only. It also doesn’t play nice with generics and I couldn’t get it to work with your use case so this is a pretty useless comment 🤷‍♂️

Read more comments on GitHub >

github_iconTop Results From Across the Web

Support parametrisable schemas · Issue #153 · colinhacks/zod
Your issue was having your generic T infer the TS type of the schema instead of the schema itself. That's necessary in order...
Read more >
Connection Schema – What It Is & 27 Ways To Support It
Supporting schemas generate curiosity in children which is a huge motivator to learning; Supporting schemas help deepen and intensify children's play; You can ......
Read more >
System monitoring with Grafana, InfluxDB and Collectd
Schema grafana. Collectd is a daemon process that runs on the system and collects information like CPU, memory, disk usage, network data, ...
Read more >
Mysql dynamic table name
Prepared statements support parameters, but you can't use them for table names. ... @AmanSanganeria: Table names are not parametrisable in T-SQL.
Read more >
Graphical Flow-based Spark Programming | Journal of Big Data
From the tool's perspective, the input is a compatible schema, and the output is a corresponding altered schema. In contrast to this, supporting...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found