anatine / zod-plugins

Plugins and utilities for Zod
591 stars 84 forks source link

[zod-nestjs] Discriminated union type inferred incorrectly #175

Open erkstruwe opened 7 months ago

erkstruwe commented 7 months ago

When using Zod's discriminatedUnion function to createZodDto, the resulting class does not infer types correctly. Minimal example:

import { createZodDto } from "@anatine/zod-nestjs"
import { z } from "zod"

const mySchema = z.discriminatedUnion("type", [
    z.object({
        type: z.literal("one"),
        oneAttribute: z.string(),
    }),
    z.object({
        type: z.literal("two"),
        twoAttribute: z.string(),
    }),
])

let a: z.infer<typeof mySchema>
setTimeout(() => {
    switch (a.type) {
        case "one":
            a.type // "one"
            a.oneAttribute // string
            break
        case "two":
            a.type // "two"
            a.oneAttribute // Error (as expected)
            break
    }
})

class MyDto extends createZodDto(mySchema) {}
let b: MyDto
setTimeout(() => {
    switch (b.type) {
        case "one":
            b.type // "one"
            b.oneAttribute // Error (unexpected)
            break
        case "two":
            b.type // "two"
            b.oneAttribute // Error (as expected)
            break
    }
})

let c: z.infer<(typeof MyDto)["zodSchema"]>
setTimeout(() => {
    switch (c.type) {
        case "one":
            c.type // "one"
            c.oneAttribute // string
            break
        case "two":
            c.type // "two"
            c.oneAttribute // Error (as expected)
            break
    }
})

In the a case, plain Zod is used and everything works as expected.

In the b case, createZodDto is used, leading to an unexpected Error "Property 'oneAttribute' does not exist on type 'MyDto'." for b.oneAttribute.

As a workaround, case c can be used.

Can we get the b case to work in zod-nestjs?

nipu-softic commented 7 months ago

facing same issue

sleekCodable commented 7 months ago

me too...