close
Skip to content

What should deepPartial be replaced with? #2854

Closed

Description

@EricImpact

It looks like deepPartial was deprecated in 3.21.0. What should be used instead?

Also just to note that the documentation at https://zod.dev/?id=deeppartial doesn't make any mention of deepPartial being deprecated.

Activity

  1. foges commented on Oct 17, 2023

    @foges

    Bumping this. There doesn't seem to be any docs about why it was deprecated or what one should use instead.

  2. josesilveiraa07 commented on Nov 3, 2023

    @josesilveiraa07

    Bumping this.

  3. kodermax commented on Nov 14, 2023

    @kodermax

    Bump

  4. iway1 commented on Nov 21, 2023

    @iway1

    im gonna lock versions and just use .deepPartial() I gueess

  5. psychedelicious commented on Nov 22, 2023

    @psychedelicious

    I noticed in #2106 the maintainer says:

    The .deepPartial API has this same problem. I'm deprecating it for the same reason.

    However, that issue is about 9 months old and there doesn't appear to be any clarity/ETA on the outcome.

  6. szulcus commented on Dec 7, 2023

    @szulcus

    Bump

  7. fmoessle commented on Dec 12, 2023

    @fmoessle

    bump

  8. scharf commented on Dec 22, 2023

    @scharf

    Bump

  9. wk-ouisense commented on Jan 2, 2024

    @wk-ouisense

    Bump 🤷‍♂️

  10. caleygoff-invitae commented on Jan 9, 2024

    @caleygoff-invitae

    bump watching this -- locking versions until an alternative is available

  11. broisnees commented on Jan 19, 2024

    @broisnees

    any update regarding the deepPartial, what should to use if this is deprecated?

  12. dannydi12 commented on Jan 30, 2024

    @dannydi12

    Also wondering what should be done here...

  13. TKasperczyk commented on Feb 22, 2024

    @TKasperczyk

    How come this is still unresolved, and even completely unanswered?

  14. cqone commented on Feb 22, 2024

    @cqone

    Bump

  15. broisnees commented on Feb 26, 2024

    @broisnees

    asdf

  16. 52 remaining items

  17. amirfarzamnia commented on May 19, 2025

    @amirfarzamnia

    🚀 Solution Available: zod-deep-partial

    I've put together a solution to address the current issue: a fully type-safe utility that deeply makes any Zod schema partial, including nested objects, arrays, and all Zod types.

    ✅ Features

    • Full Type-Safety – Built with TypeScript from the ground up.
    • Supports All Zod Types – Handles complex, nested schemas correctly.
    • Zero Dependencies – Lightweight (~10KB).
    • Focused Utility – Does one thing: deeply partializes Zod schemas.

    Get it on npm:

    https://www.npmjs.com/package/zod-deep-partial

    Source Code:

    https://github.com/amirfarzamnia/zod-deep-partial

    Documentation:

    https://amirfarzamnia.github.io/zod-deep-partial/

    It's simple to use: just import the function and apply it to your Zod schema.

    Contributions and feedback are welcome!

  18. jaens commented on May 20, 2025

    @jaens

    Supports All Zod Types – Handles complex, nested schemas correctly.

    No it doesn't.

    • It does not properly handle about half of the advanced types (by not visiting their type arguments).
    • It will infinite loop (stack overflow) on recursive types.
    • It will duplicate types that are used more than once, possibly leading to exponential time complexity.

    As already mentioned in a comment above, see https://gist.github.com/jaens/7e15ae1984bb338c86eb5e452dee3010 for the full list that needs to be handled (and something that actually does).

  19. Refzlund commented on May 31, 2025

    @Refzlund

    @antonio-ivanovski
    We understand .deepPartial() was removed in v4 due to complexity/performance issues (we hit TS limits ourselves).

    Same boat, complex indeed. We can all agree that .deepPartial leaves a bad taste in the mouth for good reasons.

    Perhaps

    1. A way to skip errors
      Ex. if(error.code == 'required') skip — this way we can skip any specifics checks when parsing, and still get other errors.
    2. Include a deepPartial-option for the .parse/.safeParse-method, that returns the .infer<T> as DeepPartial<T> (via 1st point)
      Ex. User.parse(content, { deepPartial: true })

    This way we can avoid the crazy type-gymnastics alongside the maintainence required to handle every ZodType — as well as increase the DX by explicitly stating this validation skip when parsing.

    We use it for partial updates to existing (validated) documents as well.

  20. ahrjarrett commented on Jul 15, 2025

    @ahrjarrett
    Contributor

    deepPartial is available in @traversable/zod.

    It includes the circular detection @jaens mentioned, and has been fuzz tested to ensure the implementation works as expected.

    Of course, use with care, this might be an anti-pattern, etc.

  21. dosubot commented on Jul 22, 2025

    @dosubot

    Hi @EricImpact! I'm Dosu and I’m helping the zod team.

    I'm a bot trained on Zod's codebase and issues.

    The .deepPartial() method was deprecated in Zod 3 and removed in Zod 4 due to implementation issues and because it's considered an anti-pattern by the maintainers. There is no direct alternative or official workaround for deep partial schemas in Zod 4. If you need deep partial functionality, you'll need to write your own utility or manually construct the schema as needed. You can read the official rationale in the Zod v4 changelog and PR #4095.

    The .partial() method is still available, but it only makes top-level properties optional and does not recurse into nested objects or arrays.

    Given the high community interest and ongoing confusion, tagging @colinhacks for any further clarification or guidance on recommended patterns or future plans. If you have a specific use case, feel free to share it—sometimes the community can suggest workarounds.

    If this answers your question, please close the issue.

    To reply, just mention @dosu.


    Docs are dead. Just use Dosu.

    Leave Feedback Ask Dosu about zod

  22. amirfarzamnia commented on Dec 15, 2025

    @amirfarzamnia

    🚀 Solution Available: zod-deep-partial

    This remains the most reliable approach. The zod-deep-partial npm package is purpose-built for making Zod schemas deeply partial. It has recently added support for more Zod features and now fully supports Zod v4. The project is actively maintained and will continue to receive updates. Contributions are very welcome!

    npm:

    https://www.npmjs.com/package/zod-deep-partial

    GitHub:

    https://github.com/amirfarzamnia/zod-deep-partial

    Documentation:

    https://amirfarzamnia.github.io/zod-deep-partial/

  23. jaens commented on Dec 16, 2025

    @jaens

    🤦

    🚀 Solution Available: zod-deep-partial

    This remains the most reliable approach.

    Nah, this is still AI-generated slop (although it works slightly better now).

    It still:

    • has exponential complexity for non-tree shaped schemas 💣
    • catastrophically fails due to missing proper handling for about 50% of Zod types 💀

    Not even worth an in-depth review.

  24. amirfarzamnia commented on Dec 16, 2025

    @amirfarzamnia

    🤦

    🚀 Solution Available: zod-deep-partial

    This remains the most reliable approach.

    Nah, this is still AI-generated slop (although it works slightly better now).

    It still:

    * has exponential complexity for non-tree shaped schemas 💣
    
    * catastrophically fails due to missing proper handling for about 50% of Zod types 💀
    

    Not even worth an in-depth review.

    AI-generated? I’d be genuinely interested to know which AI model could generate a codebase like this.

    Some functionality is still missing and will be added in future updates. Currently, the most important Zod schemas are supported, which should meet the needs of roughly 80% of users.

    The approach you suggested is also a solid option, especially for advanced use cases. However, for many users it may be more complex than necessary. This solution aims to provide a simpler, more approachable option while remaining reliable and maintainable in the long term.

    If it already works better than before, it will continue to improve over time.

    Thank you for taking the time to share your feedback. Contributions are always welcome.

  25. dokson commented on May 1, 2026

    @dokson
    Contributor

    Hi @PritamSangani — opened #5928 with a v4-native implementation. Tagging @jaens, @amirfarzamnia, and @colinhacks for design feedback.

    What's there

    • z.deepPartial(schema) available in both classic and mini.
    • z.mapOnSchema(schema, fn) exposed as the general traversal primitive — deepPartial is one line on top of it; deepStrict, deepReadonly, and user-defined rewrites become trivial follow-ups.
    • Cycle-safe (via Map<schema, RESOLVING|result>) — recursive lazy schemas terminate; shared sub-schemas visited once.
    • Dispatches on schema._zod.def.type, not instanceof. Custom user-defined schema types pass through cleanly instead of being silently mishandled.
    • Full v4 def coverage (object/array/tuple+rest/record/map/set/union+discriminator/intersection/optional/nullable/default/prefault/nonoptional/catch/readonly/promise/success/pipe/function/lazy). Leaves left untouched.

    Addressing the original concern

    @colinhacks — the deprecation rationale in #2106 was about the brittle instanceof switch and the proliferation of edge cases. This PR specifically tries to not reintroduce that pattern: the def.type dispatch is open under user-defined types, the cycle behaviour is explicit (terminate or throw), and the primitive is exported so derived helpers don't each duplicate the logic. Happy to iterate on naming, scope, or close as wontfix if the design direction has changed.

    Attribution

    @jaens — the traversal pattern (mapOnSchema with RESOLVING sentinel) is adapted from your gist (Apache-2.0). The v4 implementation is a rewrite (def.type dispatch, core.clone, full v4 vocabulary coverage), and attribution is in the file header. Would value your review of the v4 port — especially whether the cycle handling matches what you intended.

    On zod-deep-partial

    @amirfarzamnia — the limitations you've already heard from @jaens (no cycle detection on lazy, half the advanced types not visited, exponential blowup on shared sub-schemas) were concrete bars this PR tried to clear. Both packages can coexist; this is a proposal for an in-tree solution that aims to be a drop-in for v3 users while structurally addressing #2106.

    3807/3808 tests pass locally with 0 type errors (the one failure is an unrelated Windows-local recheck-jar env issue).

  26. dokson commented on May 1, 2026

    @dokson
    Contributor

    Update on #5928: expanded test suite to 40 cases (was 22) covering the edge cases @jaens flagged in earlier comments — discriminated unions (including the discriminator-becomes-optional collapse, now degraded to plain union to keep parsing correct), intersection, record / map / set, promise, pipe (both in/out recursed), wrapper composition (default + readonly + optional), 3-level nested objects, transform passthrough, shared sub-schema visited-once, unknown def.type passthrough. Recursive (lazy) cycle termination is verified. Full v4 test suite passes with 0 type errors.

  27. added a commit that references this issue on Aug 14, 2026
    5e60885
  28. matzeeable commented on Oct 12, 2026

    @matzeeable

    @dokson I just came across this issue via the Github Gist and find the approach of the visit() pattern (used for deepPartial) very interesting. Would it also be possible to export this visit option publicly? I have some use cases where I need to define codec() recursively for a schema to make it ready for a data lakehouse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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