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.

Incorrect error for unions with literals

See original GitHub issue

Description I use zod@2.0.0-beta.30 I want to use zod to parse structures like

type T = { val: 'a', a?: string } | { val: 'b', b?: number }

but I get incorrect error when I tries to parse structure with incorrect field’s type

Demo

import * as z from 'zod'

const Schema = z.union([
  z.object({
    val: z.literal('a'),
    a: z.ostring()
  }),
  z.object({
    val: z.literal('b'),
    b: z.onumber()
  })
])

console.log(Schema.parse({
  val: 'a',
  a: 123         
}))

Expected error

Error: [
  {
    "code": "invalid_type",
    "expected": "string",
    "received": "number",
    "path": [
      "a"
    ],
    "message": "Expected string, received number"
  }
]

Actual error

Error: [
  {
    "code": "invalid_literal_value",
    "expected": "b",
    "path": [
      "val"
    ],
    "message": "Input must be \"b\""
  }
]

Issue Analytics

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

github_iconTop GitHub Comments

7reactions
hmaurercommented, Apr 12, 2021

I have been using Zod 3 and poor error messages when using discriminated unions lead me to this issue. As @colinhacks pointed out above Zod isn’t able to guess which schema is most “relevant”, but has it been considered to add an explicit “discriminated union” construct to Zod? JSON Type Definition has a discriminator form for specifically this purpose, e.g.

{
  discriminator: "val",
  mappings: {
    "a": {
      properties: {
        a: {type: "string"}
      }
    },
    "b": {
      properties: {
        b: {type: "number"}
      }
    }
  }
}

There’s an AJV implementation as well. In Zod, it could look something like:

z.discriminatedUnion("val", {
  a: { a: z.string() },
  b: { b: z.number() },
});

If there are no immediate objections I’d be happy to work on an implementation.

1reaction
alexxandercommented, Jan 27, 2022

I implemented a function for handling discriminated unions (using zod 3.11.6). zodDiscriminatedUnion(discriminator: string, types: ZodObject[])

  • discriminator the name of the discriminator property
  • types an array of object schemas Its behaviour is very similar to that of the z.union() function. However, it only allows a union of objects, all of which need to share a discriminator property. This property must have a different value for each object in the union.

More info here: https://github.com/colinhacks/zod/issues/792#issuecomment-1023251415

Read more comments on GitHub >

github_iconTop Results From Across the Web

why is TypeScript converting string literal union type to string ...
I came across a simple case where I was expecting the union type to be retained. Here is a simple version: let foo...
Read more >
PI72248: INCORROUT WITH CONCENTRATE STATEMENTS WITH ...
It contains a view or table expression with UNION ALL. * * 2. One of the result columns from the UNION ALL branches...
Read more >
Literal types and Enums - mypy 0.991 documentation
Tagged unions​​ When you have a union of types, you can normally discriminate between each type in the union by using isinstance checks....
Read more >
Types of SQL Injection Attacks
In SQL statements, a string literal is a group of characters surrounded by ... incorrect SQL syntax which will make the application return...
Read more >
Sorbet Error Reference
Refactor the code to use module_function with only calls to method definitions or literals, or; Downgrade the file to # typed: false or...
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