-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Update zod 3 to zod 4 support in p5.js dev-2.0 #7872
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
base: dev-2.0
Are you sure you want to change the base?
Conversation
- line 325 schema `items` can be access within `def` - line 356 and 360 `_def` is deprecated , use `def` or directly use `options` - line 393 `zodErrorObj.errors[0]` changes to `zodErrorObj.errors[0]` - line 410 `union error` changes to `errors` - line 414 and 459 , `received` changes to `message` ## Important In constants.js, Symbols aren't considered literal values, nor can they be simply compared with ===. This was an oversight in Zod 3.
According to zod 4 , error message are more elaborated
🎉 Thanks for opening this pull request! Please check out our contributing guidelines if you haven't already. And be sure to add yourself to the list of contributors on the readme page! |
Hi @madhav2348 ! Thanks for working on this. From the tests, looks like the zod update in package.json itself isn't part of the PR? |
My apologies, Thank you for figuring out. I was trying to reproduce the failed test case by switching back and forth between Zod 3 and Zod 4 versions to confirm which leads to uncommitted package.json changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking this on! Are the changed property names and error types due to the originals no longer existing in zod 4? Just for my own understanding, did you come across any docs explaining those differences?
to match the test cases - split the error messages, to get a type in line 418 and 462 - `actualType` will never be undefined which is checked in line 394 so make it undefined in line 430 to pass all test cases
I went through the migration docs, but they haven't covered all the changes. The changes I made are by going through the source code of Zod 4. Thank you |
@@ -230,6 +230,10 @@ function validateParams(p5, fn, lifecycles) { | |||
param = param?.replace(/^\.\.\.(.+)\[\]$/, '$1'); | |||
|
|||
let schema = generateTypeSchema(param); | |||
if (!schema || typeof schema.optional !== 'function') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious what test case was generating an undefined schema? This works as a fallback, but I wonder if there's potentially a deeper issue needing fixing that this hides.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Zod 3, an undefined
somehow works fine schema.optional()
, but in Zod 4 throws a TypeError
, and 181 test cases failed in WebGL, Type and Visual . So using z.any()
as safeguard
Internal clip operations do not enable stencil test for future draw cycles
TypeError: Cannot read properties of undefined (reading 'optin')
- /node_modules/.vite/deps/zod_v4.js:2884:86
- /node_modules/.vite/deps/zod_v4.js:2884:56
- /node_modules/.vite/deps/zod_v4.js:464:5
- /node_modules/.vite/deps/zod_v4.js:10325:13
- /node_modules/.vite/deps/zod_v4.js:464:5
- /node_modules/.vite/deps/zod_v4.js:479:5
- /node_modules/.vite/deps/zod_v4.js:10336:10
- /src/core/friendly_errors/param_validator.js:284:26
matches expected screenshots
TypeError: schema.optional is not a function
- /src/core/friendly_errors/param_validator.js:238:25
- /src/core/friendly_errors/param_validator.js:276:21
- /src/core/friendly_errors/param_validator.js:276:12
- /src/core/friendly_errors/param_validator.js:274:27
- /src/core/friendly_errors/param_validator.js:271:39
- /src/core/friendly_errors/param_validator.js:538:24
- /src/core/friendly_errors/param_validator.js:569:16
This could work by throw an error here to catch real bugs early instead of hiding them with z.any().
Its just a thought, not sure if this would works,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried adding this:
let schema = generateTypeSchema(param);
if (typeof schema.optional !== 'function') {
console.log(param, schema);
}
...and then running just that failing test by changing it to test.only(...)
, and I see this log:

So it looks like z.function()
is responsible for this? I think we don't want to turn this into an any
type, but rather, figure out how we can keep it a function, but make it possible to be optional. Maybe something is different about how functions are treated in zod 4?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad. In zod 4, the docs say:
'' The result of z.function() is no longer a Zod schema. Instead, it acts as a standalone "function factory" for defining Zod-validated functions. The API has also changed; you define an input and output schema upfront, instead of using args() and .returns() methods. ''
Do you have any suggestions on this? Because any()
feels like a brute-force solution.
I was considering a custom wrapper using z.custom()
. But would love to hear your thoughts on this
https://zod.dev/v4/changelog?id=zfunction
https://zod.dev/api?id=functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The quick change would be to set the input parameters to any, and the output type to any. We could in theory check the parameters too, but I think that's hard to do at runtime, so I think just making the parameters/return types any will be sufficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes made as suggested.
Let me know if further adjustments are needed!
Thank you
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey sorry for the delay, I think I may have misinterpreted what you said. I think we still want to use a zod function, but where the zod function's return type is any()
. But I think we still need to use z.function()
rather than immediately returning any()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@davepagurek, Can you help with this, because falling back to z.any()
is a viable solution here.
According to Zod 4, I use output()
because returns()
methods no longer uses , so not returning zod function's type immediatly to any()
if (schema.def.type === 'function') {
schema = schema.output(z.any())
}
which follow the new API
But encounter some error in zod tuple in overloadSchemas
TypeError: Cannot read properties of undefined (reading 'optin')
┌[http://localhost:63315/node_modules/.vite/deps/zod_v4.js?v=621f9dc0:2884:86]
Error at line 2884 in ()
└[http://localhost:63315/node_modules/.vite/deps/zod_v4.js?v=621f9dc0:2884:56]
Called from line 2884 in ()
└[http://localhost:63315/node_modules/.vite/deps/zod_v4.js?v=621f9dc0:464:5]
Called from line 464 in $ZodTuple.init()
└[http://localhost:63315/node_modules/.vite/deps/zod_v4.js?v=621f9dc0:10325:13]
Called from line 10325 in ()
└[http://localhost:63315/node_modules/.vite/deps/zod_v4.js?v=621f9dc0:464:5]
Called from line 464 in init()
└[http://localhost:63315/node_modules/.vite/deps/zod_v4.js?v=621f9dc0:479:5]
Called from line 479 in new ZodTuple()
└[http://localhost:63315/node_modules/.vite/deps/zod_v4.js?v=621f9dc0:10336:10]
Called from line 10336 in Object.tuple()
└[http://localhost:63315/src/core/friendly_errors/param_validator.js:288:26]
Called from line 288 in ()
and p5 error
🌸 p5.js says:
[zod_v4.js?v=621f9dc0, line 2884] Cannot read property of undefined. Check the line number in error and make sure the variable which is being operated is not undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we try using z.custom
to just check if the argument instanceof Function
? so, z.custom((val) => val instanceof Function)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That wouldn't check the arguments/return value, but that's likely sufficient.
- z.function() is no longer a Zod schema. Instead, it acts as a standalone "function factory" for defining Zod-validated functions. - .def.type checks schema type. If its `'function'`, fallback to `z.any()`
Resolves #7833
Changes:
items
can be accessed withindef
_def
is deprecated, usedef
or directly useoptions
zodErrorObj.errors[0]
changes tozodErrorObj.issues[0]
union error
changes toerrors
received
changes tomessage
Important
constant.js have some variable which are Symbols , according to zod 4, Symbols aren't considered literal values, nor can they be simply compared with ===. This was an oversight in Zod 3.
PR Checklist
npm run lint
passes