Skip to content

[V4] z.union members with overridden recursive getters are typed as any #4931

@andyburris

Description

@andyburris

This is quite an edge case, but recursive typing breaks when a getter method is

  1. overriding a getter method in the object it's extending and
  2. one of nodes in the recursion is a z.union that contains the schema holding the getter.

In this case, the getter will be typed as any, and thus the schema holding that getter is also any. More confusingly, only the first member of the union will be typed as any if there are multiple such cases. It's kinda confusing, so hopefully this code makes sense of it:

import { z } from "zod";

const NodeBase = z.object({
    id: z.string(),
    get children() { return z.array(Node).optional() },
});

// typed as any
const NodeOne = NodeBase.extend({
    name: z.literal("nodeOne"),
    // if this is commented out, NodeTwo becomes any
    get children() { return z.array(Node) },
});

// also typed as any
// const NodeOne = z.object({
//     ...NodeBase.shape,
//     name: z.literal("nodeOne"),
//     get children() { return z.array(Node) },
// });

// oddly, this is typed correctly
const NodeTwo = NodeBase.extend({
    name: z.literal("nodeTwo"),
    get children() { return z.array(Node) },
});

const Node = z.union([NodeOne, NodeTwo]);

I'm wondering if this is a bug in Zod or if it's an inherent Typescript limitation, and either way, is there any way to work around it?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions