npm yup 1.0.0-alpha.3
Better, Faster, Stronger...generics

latest releases: 1.4.0, 1.3.3, 1.3.2...
2 years ago

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 tsc on the command line and in editor. It also removes the need for the SchemaOf helper which worked...poorly.

Instead the ObjectSchema class 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.

Note that the generics on the object() factory method are still the "object shape, meaning object<Folder>() won't work as expected. This is a compromise between the two strategies for handling generics and allows for an accurate type on object().getDefault()

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:

const nullableRequiredString = string().nullable().required()

nullableRequiredString.cast(null) // -> null

nullableRequiredString.validate(null) // ValidationError("this is required and cannot be null")

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(), defined and required are all mutually dependent methods. Meaning string().nullable().defined().required() produces a schema where the value must be a string, and not null or undefined. The effect of this is that the type of a cast() is now accurate and the same as the type returned from validate.

Don't miss a new yup release

NewReleases is sending notifications on new releases.