feat: More intuitive Object generics, faster types#1540
Merged
Conversation
f1f6a8c to
93a2f4e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes the object generics to store the derived type instead of the object shape. This imposes a few limitations on type accuracy at the edges, but dramatically speeds up the type processing by
tscon the command line and in editor. It also removes the need for theSchemaOfhelper which worked...poorly.Instead the
ObjectSchemaclass accepts a plain type as its first generic:interface Folder { id: ObjectId, label: string, files?: File[] } - const folder: SchemaOf<Folder, ObjectId | File> = object({ - id: mixed<ObjectId>().defined(), - label: string().defined(), - files: array(mixed<File>().defined()) - }) + const folder: ObjectSchema<Folder> = object({ + id: mixed<ObjectId>().defined(), + label: string().defined(), + files: array(mixed<File>().defined()) + })It's a small diff, but big improvement in type accuracy and usability, especially with custom schema for class instances.
A number of the improvements here are made possible by simplifications to yup's API and logic, this introduces a few breaking changes though most are small and easily migrated from.
Nullability and presence
This is the largest, and likely most disruptive change. Prior yup allowed for patterns like:
This may seem unintuitive behavior (and it is) but allowed for a common client side validation case, where we want to use a single schema to parse server data, as well as validate user input. In other words, a server might return invalid "default" values that should still fail when trying to submit.
Now,
nullable(),definedandrequiredare all mutually dependent methods. Meaningstring().nullable().defined().required()produces a schema where the value must be a string, and notnullorundefined. The effect of this is that the type of acast()is now accurate and the same as the type returned fromvalidate.When signature
The following API has been simplified to be clearer, and easier to type
string().when('foo', { is: 'bar', - then: string().required() + then: schema => schema.required() })Concat behavior
Current concat doesn't work super well and will likely be removed as it's not very useful. It's primary use was supporting the now-defunct
when()api above. More on this coming later