Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What should deepPartial be replaced with? #2854

Open
EricImpact opened this issue Oct 10, 2023 · 57 comments
Open

What should deepPartial be replaced with? #2854

EricImpact opened this issue Oct 10, 2023 · 57 comments

Comments

@EricImpact
Copy link

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.

@foges
Copy link

foges commented Oct 17, 2023

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

@josesilveiraa07
Copy link

Bumping this.

@kodermax
Copy link

Bump

@iway1
Copy link

iway1 commented Nov 21, 2023

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

@psychedelicious
Copy link

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.

@szulcus
Copy link

szulcus commented Dec 7, 2023

Bump

@fmoessle
Copy link

bump

@scharf
Copy link

scharf commented Dec 22, 2023

Bump

@wk-ouisense
Copy link

Bump 🤷‍♂️

@caleygoff-invitae
Copy link

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

@broisnischal
Copy link

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

@dannydi12
Copy link

Also wondering what should be done here...

@TKasperczyk
Copy link

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

@cqone
Copy link

cqone commented Feb 22, 2024

Bump

@broisnischal
Copy link

asdf

@lukepighetti
Copy link

What are folks using when deepPartial is deprecated?

@EternalEnR
Copy link

Bump

1 similar comment
@GR1NYAoff
Copy link

Bump

@broisnischal
Copy link

why is zod.switch docs not available in their docs?

@jion
Copy link

jion commented Mar 8, 2024

bump!

@radzserg
Copy link

bump

6 similar comments
@aryan877
Copy link

bump

@dmytro-rodionov-tes
Copy link

bump

@wangcongyi
Copy link

bump

@MaximBuz
Copy link

bump

@miraroot
Copy link

bump

@elkofy
Copy link

elkofy commented Apr 23, 2024

bump

@PierreBeucher
Copy link

PierreBeucher commented Apr 25, 2024

Was about to add yet another not-very-useful "bump" but instead... Can please a maintainer step-in, if only to explain why this is deprecated ? Thanks :)

@szulcus
Copy link

szulcus commented Apr 25, 2024

7 months and 27 bumps later, we're still waiting for someone to correct it 😕

@EricImpact
Copy link
Author

@colinhacks There is a lot of interest here in deepPartial and whatever its replacement should be. Would be great to get some clarification from you.

@mkykadir
Copy link

mkykadir commented May 9, 2024

bumping this as well 👍

@JuanPabloSebey
Copy link

bump

@meirzhhan
Copy link

const state: Partial<StateSchema> = {
  profile: {
    data: {
      a: 'a',
      b: 'b'
  } as ProfileSchema,
};

interface StateSchema {
  profile: ProfileSchema,
  other: OtherSchema,
}

interface ProfileSchema {
  a: string,
  b: string
}

@MrBns
Copy link

MrBns commented May 22, 2024

whats wrong here ?
a popular validation library .. deprecated without any reason ?

@abiriadev
Copy link

The only solution currently available is to manually append .partial() recursively by iterating over .shape.

@psychedelicious
Copy link

a popular validation library .. deprecated without any reason ?

It's not deprecated without reason. The reason is described in #2106.

@nasserakhtersi
Copy link

bump

@dev-opus
Copy link

The only solution currently available is to manually append .partial() recursively by iterating over .shape.

hello, would be super grateful if you could show a little demo for this

@tobi110289
Copy link

Hello Zod Team,

I hope this message finds you well! First and foremost, I want to extend my heartfelt appreciation for your continuous efforts in maintaining and enhancing the Zod library. It has been an invaluable asset in ensuring robust validation processes in my projects, and I am truly grateful for your hard work and dedication.

I am writing to seek some guidance regarding the recent deprecation of the deepPartial utility. I noticed that it has been marked as deprecated, and I could not find information on the recommended alternative. Could you kindly provide some insights into what should be used in place of deepPartial? This utility has been instrumental in my current projects, and understanding its successor would greatly aid in transitioning my codebase with minimal disruptions.

Additionally, if there's a migration guide or any documentation regarding this change, I would be grateful if you could point me towards it. Ensuring compatibility and taking advantage of the latest features and best practices you recommend would be incredibly beneficial.

Thank you again for your exceptional support and for creating such a fantastic tool. I look forward to your advice and continue to be excited about the future developments in Zod.

Warm regards,
Tobi

PS: Bump

@lenovouser
Copy link

@tobi110289 hello ChatGPT 😆

@Catlike14
Copy link

hello ChatGPT 😆

Hello! 😆 How can I assist you today?

@imnique
Copy link

imnique commented Jul 13, 2024

bump

1 similar comment
@enricoros
Copy link

bump

@sganot-r7
Copy link

bump 🤦‍♀️

@simonsankar
Copy link

fist

@cubxx
Copy link

cubxx commented Aug 11, 2024

bump

@ArianHamdi
Copy link

Bump

@Katli95
Copy link

Katli95 commented Aug 16, 2024

Obligatory: Sorry, I know I'm just piling on

Allright guys, jeeesus, can we stop the spam, I'm fairly certain by now that the maintainers know about the issue and a "Bump" isn't going to suddenly make them work on it. This is just the way open source is some times, and we'll either have to wait until they get back to us or someone contact the maintainers directly to get working on it themselves.

That being said @colinhacks or any other maintainer (if there's any), it would be incredibly helpful if you provided further insight into why deepPartial has been marked as deprecated and more importantly what users should migrate towards. Sorry if you've outlined this elsewhere but please then just link it and close the issue.

@Wazbat
Copy link

Wazbat commented Aug 21, 2024

I think the main reason as to why there are constant bumps is specifically because no maintainer has replied or acknowledged this, so people aren't sure what the next steps are. People are very busy which is perfectly understandable

@afzalali27
Copy link

Bump

@deathcrafter
Copy link

Apparently this:

zod/src/types.ts

Line 2382 in 8552233

function deepPartialify(schema: ZodTypeAny): any {

import { ZodArray, ZodNullable, ZodObject, ZodOptional, ZodTuple } from "zod";

/**
 * Recursively transforms a Zod schema to make all fields optional, allowing for deep partial objects.
 *
 * @template T
 * @param {T} schema - The Zod schema to transform.
 * @returns {T} The transformed Zod schema with all fields made optional.
 */
function deepPartialify(schema) {
  if (schema instanceof ZodObject) {
    const newShape = {};

    for (const key in schema.shape) {
      const fieldSchema = schema.shape[key];
      newShape[key] = ZodOptional.create(deepPartialify(fieldSchema));
    }

    return new ZodObject({
      ...schema._def,
      shape: () => newShape,
    });
  } else if (schema instanceof ZodArray) {
    return new ZodArray({
      ...schema._def,
      type: deepPartialify(schema.element),
    });
  } else if (schema instanceof ZodOptional) {
    return ZodOptional.create(deepPartialify(schema.unwrap()));
  } else if (schema instanceof ZodNullable) {
    return ZodNullable.create(deepPartialify(schema.unwrap()));
  } else if (schema instanceof ZodTuple) {
    return ZodTuple.create(
      schema.items.map(item => deepPartialify(item))
    );
  } else {
    return schema;
  }
}

Now, I couldn't make the typing work in JSDoc, but I think someone else can, or just use TypeScript. I am bound to JS for my project so I can't look into proper typing.

@largis21
Copy link

With type def:

/* eslint @typescript-eslint/no-explicit-any: 0 */

// This is stolen from the zod repo
//
// z.ZodObject.deepPartial is deprecated, but there is no good alternative yet
// Deprectation issue: https://github.com/colinhacks/zod/issues/2106
// Also related: https://github.com/colinhacks/zod/issues/2854

import { z } from "zod";

type ZodDeepPartial<T extends z.ZodTypeAny> =
  T extends z.ZodObject<z.ZodRawShape>
  ? z.ZodObject<
    {
      [k in keyof T["shape"]]: z.ZodOptional<ZodDeepPartial<T["shape"][k]>>;
    },
    T["_def"]["unknownKeys"],
    T["_def"]["catchall"]
  >
  : T extends z.ZodArray<infer Type, infer Card>
  ? z.ZodArray<ZodDeepPartial<Type>, Card>
  : T extends z.ZodOptional<infer Type>
  ? z.ZodOptional<ZodDeepPartial<Type>>
  : T extends z.ZodNullable<infer Type>
  ? z.ZodNullable<ZodDeepPartial<Type>>
  : T extends z.ZodTuple<infer Items>
  ? {
    [k in keyof Items]: Items[k] extends z.ZodTypeAny
    ? ZodDeepPartial<Items[k]>
    : never;
  } extends infer PI
  ? PI extends z.ZodTupleItems
  ? z.ZodTuple<PI>
  : never
  : never
  : T;

export function deepPartialify<T extends z.ZodTypeAny>(
  schema: T,
): ZodDeepPartial<T> {
  return _deepPartialify(schema);
}

function _deepPartialify(schema: z.ZodTypeAny): any {
  if (schema instanceof z.ZodObject) {
    const newShape: any = {};

    for (const key in schema.shape) {
      const fieldSchema = schema.shape[key];
      newShape[key] = z.ZodOptional.create(_deepPartialify(fieldSchema));
    }
    return new z.ZodObject({
      ...schema._def,
      shape: () => newShape,
    }) as any;
  } else if (schema instanceof z.ZodArray) {
    return new z.ZodArray({
      ...schema._def,
      type: _deepPartialify(schema.element),
    });
  } else if (schema instanceof z.ZodOptional) {
    return z.ZodOptional.create(_deepPartialify(schema.unwrap()));
  } else if (schema instanceof z.ZodNullable) {
    return z.ZodNullable.create(_deepPartialify(schema.unwrap()));
  } else if (schema instanceof z.ZodTuple) {
    return z.ZodTuple.create(
      schema.items.map((item: any) => _deepPartialify(item)),
    );
  } else {
    return schema;
  }
}

@AJEdgarCraft
Copy link

I'm not a developer, and don't understand why the documentation hasn't been updated for the deprecation of .deepPartial() or why almost a year later there hasn't been a response to the inquiry. I hope the maintainers are well.

For anyone who is looking for a basic manual approach to handle nested partial() implementations, this is what I had figured out in my scenario:

const newSchema = parent.schema.partial().extend({
	nestedObject: parent.schema.shape.nestedObject.partial(),
	nestedOptionalArrayOfObjects: parent.schema.shape.nestedOptionalArrayOfObjects
		.unwrap()
		.element.partial()
		.array()
		.nonempty()
		.optional(),
});

If you're utilizing .refine() on a z.object you'll need to use:

yourSchema._def.schema.shape.nestedObject.partial()

If you're utilizing .refine on a union of objects I'm completely lost there. Best of luck.

@jpierson-at-riis
Copy link

Bump

@jaens
Copy link

jaens commented Oct 24, 2024

The original function and all the solutions here are subtly incorrect.

They will:

  • not work with schemas with advanced types (unions, intersections, brands, effects etc.)
  • completely break on recursive types
  • drop metadata

A correct solution is theoretically possible, considering that the Zod<T> type is a standard recursive algebra (analogous to abstract syntax trees) and permits common recursion schemes (eg. bottom-up and top-down map) to rewrite it.

My implementation that tries to fulfill all criteria is available here:

https://gist.github.com/jaens/7e15ae1984bb338c86eb5e452dee3010

Note that it's currently missing type inference, so it's mostly useful for run-time validation with pre-existing types, not when types are defined directly from Zod schemas.

Unfortunately mapOnSchema is not directly representable as a type-level function (ie. MapOnSchema<TSchema, TFn>) due to TypeScript deficiencies with higher-kinded types: generics - Higher-order type functions in TypeScript? - Stack Overflow.

That's probably not a blocker though, since there might be possible solutions not involving HKTs, such as overloaded functions.

And in any case, it's still possible to type each function (eg. deepPartial, deepStrict) that uses mapOnSchema separately (although with a lot of copy-pasta).

@Alexander-ilyin3
Copy link

Alexander-ilyin3 commented Dec 10, 2024

My implementation that tries to fulfill all criteria is available here:

https://gist.github.com/jaens/7e15ae1984bb338c86eb5e452dee3010

As I mentioned on that repo. Careful with current version of the code. Oct 24 2024 revision.
It is not working with unions. Only first union passes the validation.

And I fail to fix it myself. Maybe someone could help there? :)

Yeah. Check this out

@jaens
Copy link

jaens commented Dec 16, 2024

@Alexander-ilyin3 As I commented in the gist, the problem was not with the library, but with your understanding of Zod. (which does unintuitive but technically correct things with partial objects in unions)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests