Ask Sawal

Discussion Forum
Notification Icon1
Write Answer Icon
Add Question Icon

When yup validation?

1 Answer(s) Available
Answer # 1 #

Yup is a schema builder for runtime value parsing and validation. Define a schema, transform a value to match, assert the shape of an existing value, or both. Yup schema are extremely expressive and allow modeling complex, interdependent validations, or value transformation.

Killer Features:

Schema are comprised of parsing actions (transforms) as well as assertions (tests) about the input value. Validate an input value to parse it and run the configured set of assertions. Chain together methods to build a schema.

Use a schema to coerce or "cast" an input value into the correct type, and optionally transform that value into more concrete and specific values, without making further assertions.

Know that your input value is already parsed? You can "strictly" validate an input, and avoid the overhead of running parsing logic.

Schema definitions, are comprised of parsing "transforms" which manipulate inputs into the desired shape and type, "tests", which make assertions over parsed data. Schema also store a bunch of "metadata", details about the schema itself, which can be used to improve error messages, build tools that dynamically consume schema, or serialize schema into another format.

In order to be maximally flexible yup allows running both parsing and assertions separately to match specific needs

Each built-in type implements basic type parsing, which comes in handy when parsing serialized data, such as JSON. Additionally types implement type specific transforms that can be enabled.

Custom transforms can be added

Transforms form a "pipeline", where the value of a previous transform is piped into the next one. When an input value is undefined yup will apply the schema default if it's configured.

Yup schema run "tests" over input values. Tests assert that inputs conform to some criteria. Tests are distinct from transforms, in that they do not change or alter the input (or its type) and are usually reserved for checks that are hard, if not impossible, to represent in static types.

As with transforms, tests can be customized on the fly

In the simplest case a test function returns true or false depending on the whether the check passed. In the case of a failing test, yup will throw a ValidationError with your (or the default) message for that test. ValidationErrors also contain a bunch of other metadata about the test, including it's name, what arguments (if any) it was called with, and the path to the failing field in the case of a nested validation.

Error messages can also be constructed on the fly to customize how the schema fails.

Schema are immutable, each method call returns a new schema object. Reuse and pass them around without fear of mutating another instance.

Yup schema produce static TypeScript interfaces. Use InferType to extract that interface:

A schema's default is used when casting produces an undefined output value. Because of this, setting a default affects the output type of the schema, essentially marking it as "defined()".

In some cases a TypeScript type already exists, and you want to ensure that your schema produces a compatible type:

You can use TypeScript's interface merging behavior to extend the schema types if needed. Type extensions should go in an "ambient" type definition file such as your globals.d.ts. Remember to actually extend the yup type in your application code!

You must have the strictNullChecks compiler option enabled for type inference to work.

We also recommend settings strictFunctionTypes to false, for functionally better types. Yes this reduces overall soundness, however TypeScript already disables this check for methods and constructors (note from TS docs):

Your mileage will vary, but we've found that this check doesn't prevent many of real bugs, while increasing the amount of onerous explicit type casting in apps.

Default error messages can be customized for when no message is provided with a validation test. If any message is missing in the custom dictionary the error message will default to Yup's one.

If you need multi-language support, yup has got you covered. The function setLocale accepts functions that can be used to generate error objects with translation keys and values. These can be fed it into your favorite i18n library.

The module export.

For nested schemas, reach will retrieve an inner schema based on the provided path.

For nested schemas that need to resolve dynamically, you can provide a value and optionally a context object.

Adds a new method to the core schema types. A friendlier convenience method for schemaType.prototype[name] = method.

If you want to add a method to ALL schema types, extend the abstract base class: Schema

Creates a reference to another sibling or sibling descendant field. Refs are resolved at validation/cast time and supported where specified. Refs are evaluated in the proper order so that the ref value is resolved before the field using the ref (be careful of circular dependencies!).

Creates a schema that is evaluated at validation/cast time. Useful for creating recursive schema like Trees, for polymorphic fields and arrays.

CAUTION! When defining parent-child recursive object schema, you want to reset the default() to null on the child—otherwise the object will infinitely nest itself when you cast it!

Thrown on failed validations, with the following properties

Schema is the abstract base class that all schema type inherit from. It provides a number of base methods and properties to all other schema types.

Creates a deep copy of the schema. Clone is used internally to return a new schema with every schema state change.

Overrides the key name which is used in error messages.

Adds to a metadata object, useful for storing data with a schema, that doesn't belong the cast object itself.

Collects schema details (like meta, labels, and active tests) into a serializable description object.

For schema with dynamic components (references, lazy, or conditions), describe requires more context to accurately return the schema description. In these cases provide options

And below are the description types, which differ a bit depending on the schema type.

Creates a new instance of the schema by combining two schemas. Only schemas of the same type can be concatenated. concat is not a "merge" function in the sense that all settings from the provided schema, override ones in the base, including type, presence and nullability.

Returns the parses and validates an input value, returning the parsed value or throwing an error. This method is asynchronous and returns a Promise object, that is fulfilled with the value, or rejected with a ValidationError.

Provide options to more specifically control the behavior of validate.

Runs validatations synchronously if possible and returns the resulting value, or throws a ValidationError. Accepts all the same options as validate.

Synchronous validation only works if there are no configured async tests, e.g tests that return a Promise. For instance this will work:

however this will not:

Validate a deeply nested path within the schema. Similar to how reach works, but uses the resulting schema as the subject for validation.

Same as validateAt but synchronous.

Returns true when the passed in value matches the schema. isValid is asynchronous and returns a Promise object.

Takes the same options as validate().

Synchronously returns true when the passed in value matches the schema.

Takes the same options as validateSync() and has the same caveats around async tests.

Attempts to coerce the passed in value to a value that matches the schema. For example: '5' will cast to 5 when using the number() type. Failed casts generally return null, but may also return results like NaN and unexpected strings.

Provide options to more specifically control the behavior of validate.

Runs a type check against the passed in value. It returns true if it matches, it does not cast the value. When nullable() is set null is considered a valid value of the type. You should use isType for all Schema type checks.

Sets the strict option to true. Strict schemas skip coercion and transformation attempts, validating the value "as is".

Marks a schema to be removed from an output object. Only works as a nested schema.

Schema with strip enabled have an inferred type of never, allowing them to be removed from the overall type:

First the legally required Rich Hickey quote:

withMutation allows you to mutate the schema in place, instead of the default behavior which clones before each change. Generally this isn't necessary since the vast majority of schema changes happen during the initial declaration, and only happen once over the lifetime of the schema, so performance isn't an issue. However certain mutations do occur at cast/validation time, (such as conditional schema using when()), or when instantiating a schema object.

Sets a default value to use when the value is undefined. Defaults are created after transformations are executed, but before validations, to help ensure that safe defaults are specified. The default value will be cloned on each use, which can incur performance penalty for objects and arrays. To avoid this overhead you can also pass a function that returns a new default. Note that null is considered a separate non-empty value.

Retrieve a previously set default value. getDefault will resolve any conditions that may alter the default. Optionally pass options with context (for more info on context see Schema.validate).

Indicates that null is a valid value for the schema. Without nullable() null is treated as a different type and will fail Schema.isType() checks.

The opposite of nullable, removes null from valid type values for the schema. Schema are non nullable by default.

Require a value for the schema. All field values apart from undefined meet this requirement.

The opposite of defined() allows undefined values for the given type.

Mark the schema as required, which will not allow undefined or null as a value. required negates the effects of calling optional() and nullable()

Mark the schema as not required. This is a shortcut for schema.nullable().optional();

Define an error message for failed type checks. The ${value} and ${type} interpolation can be used in the message argument.

Only allow values from set of values. Values added are removed from any notOneOf values if present. The ${values} interpolation can be used in the message argument. If a ref or refs are provided, the ${resolved} interpolation can be used in the message argument to get the resolved values that were checked at validation time.

Note that undefined does not fail this validator, even when undefined is not included in arrayOfValues. If you don't want undefined to be a valid value, you can use Schema.required.

Disallow values from a set of values. Values added are removed from oneOf values if present. The ${values} interpolation can be used in the message argument. If a ref or refs are provided, the ${resolved} interpolation can be used in the message argument to get the resolved values that were checked at validation time.

Adjust the schema based on a sibling or sibling children fields. You can provide an object literal where the key is is value or a matcher function, then provides the true schema and/or otherwise for the failure condition.

is conditions are strictly compared (===) if you want to use a different form of equality you can provide a function like: is: (value) => value == true.

You can also prefix properties with $ to specify a property that is dependent on context passed in by validate() or cast instead of the input value.

when conditions are additive.

then and otherwise are specified functions (schema: Schema) => Schema.

You can also specify more than one dependent key, in which case each value will be spread as an argument.

Alternatively you can provide a function that returns a schema, called with an array of values for each provided key the current schema.

Adds a test function to the validation chain. Tests are run after any object is cast. Many types have some tests built in, but you can create custom ones easily. In order to allow asynchronous custom validations all (or no) tests are run asynchronously. A consequence of this is that test execution order cannot be guaranteed.

All tests must provide a name, an error message and a validation function that must return true when the current value is valid and false or a ValidationError otherwise. To make a test async return a promise that resolves true or false or a ValidationError.

For the message argument you can provide a string which will interpolate certain values if specified using the ${param} syntax. By default all test messages are passed a path value which is valuable in nested schemas.

The test function is called with the current value. For more advanced validations you can use the alternate signature to provide more options (see below):

Test functions are called with a special context value, as the second argument, that exposes some useful metadata and functions. For non arrow functions, the test context is also set as the function this. Watch out, if you access it via this it won't work in an arrow function.

Alternative test(..) signature. options is an object containing some of the following options:

In the case of mixing exclusive and non-exclusive tests the following logic is used. If a non-exclusive test is added to a schema with an exclusive test of the same name the exclusive test is removed and further tests of the same name will be stacked.

If an exclusive test is added to a schema with non-exclusive tests of the same name the previous tests are removed and further tests of the same name will replace each other.

Adds a transformation to the transform chain. Transformations are central to the casting process, default transforms for each type coerce values to the specific type (as verified by isType()). transforms are run before validations and only applied when the schema is not marked as strict (the default). Some types have built in transformations.

Transformations are useful for arbitrarily altering how the object is cast, however, you should take care not to mutate the passed in value. Transforms are run sequentially so each value represents the current state of the cast, you can use the originalValue param if you need to work on the raw initial value.

Each types will handle basic coercion of values to the proper type for you, but occasionally you may want to adjust or refine the default behavior. For example, if you wanted to use a different date parsing strategy than the default one you could do that with a transform.

Creates a schema that matches all types, or just the ones you configure. Inherits from Schema. Mixed types extends {} by default instead of any or unknown. This is because in TypeScript {} means anything that isn't null or undefined which yup treats distinctly.

Custom types can be implemented by passing a type check function. This will also narrow the TypeScript type for the schema.

Define a string schema. Inherits from Schema.

By default, the cast logic of string is to call toString on the value if it exists.

empty values are not coerced (use ensure() to coerce empty values to empty strings).

Failed casts return the input value.

The same as the mixed() schema required, except that empty strings are also considered 'missing' values.

Set a required length for the string value. The ${length} interpolation can be used in the message argument

Set a minimum length limit for the string value. The ${min} interpolation can be used in the message argument

Set a maximum length limit for the string value. The ${max} interpolation can be used in the message argument

Provide an arbitrary regex to match the value against.

An alternate signature for string.matches with an options object. excludeEmptyString, when true, short circuits the regex test when the value is an empty string, making it a easier to avoid matching nothing without complicating the regex.

Validates the value as an email address using the same regex as defined by the HTML spec.

WATCH OUT: Validating email addresses is nearly impossible with just code. Different clients and servers accept different things and many diverge from the various specs defining "valid" emails. The ONLY real way to validate an email address is to send a verification email to it and check that the user got it. With that in mind, yup picks a relatively simple regex that does not cover all cases, but aligns with browser input validation behavior since HTML forms are a common use case for yup.

If you have more specific needs please override the email method with your own logic or regex:

Validates the value as a valid URL via a regex.

Validates the value as a valid UUID via a regex.

Transforms undefined and null values to an empty string along with setting the default to an empty string.

Transforms string values by removing leading and trailing whitespace. If strict() is set it will only validate that the value is trimmed.

Transforms the string value to lowercase. If strict() is set it will only validate that the value is lowercase.

Transforms the string value to uppercase. If strict() is set it will only validate that the value is uppercase.

Define a number schema. Inherits from Schema.

The default cast logic of number is: parseFloat.

Failed casts return NaN.

Set the minimum value allowed. The ${min} interpolation can be used in the message argument.

Set the maximum value allowed. The ${max} interpolation can be used in the message argument.

Value must be less than max. The ${less} interpolation can be used in the message argument.

Value must be strictly greater than min. The ${more} interpolation can be used in the message argument.

Value must be a positive number.

Value must be a negative number.

Validates that a number is an integer.

Transformation that coerces the value to an integer by stripping off the digits to the right of the decimal point.

Adjusts the value via the specified method of Math (defaults to 'round').

Define a boolean schema. Inherits from Schema.

Define a Date schema. By default ISO date strings will parse correctly, for more robust parsing options see the extending schema types at the end of the readme. Inherits from Schema.

The default cast logic of date is pass the value to the Date constructor, failing that, it will attempt to parse the date as an ISO date string.

Failed casts return an invalid Date.

Set the minimum date allowed. When a string is provided it will attempt to cast to a date first and use the result as the limit.

Set the maximum date allowed, When a string is provided it will attempt to cast to a date first and use the result as the limit.

Define an array schema. Arrays can be typed or not, When specifying the element type, cast and isValid will apply to the elements as well. Options passed into isValid are also passed to child schemas.

Inherits from Schema.

You can also pass a subtype schema to the array constructor as a convenience.

Arrays have no default casting behavior.

Specify the schema of array elements. of() is optional and when omitted the array schema will not validate its contents.

Attempt to parse input string values as JSON using JSON.parse.

Set a specific length requirement for the array. The ${length} interpolation can be used in the message argument.

Set a minimum length limit for the array. The ${min} interpolation can be used in the message argument.

Set a maximum length limit for the array. The ${max} interpolation can be used in the message argument.

Ensures that the value is an array, by setting the default to [] and transforming null and undefined values to an empty array as well. Any non-empty, non-array value will be wrapped in an array.

Removes falsey values from the array. Providing a rejecter function lets you specify the rejection criteria yourself.

Tuples, are fixed length arrays where each item has a distinct type.

Inherits from Schema.

tuples have no default casting behavior.

Define an object schema. Options passed into isValid are also passed to child schemas. Inherits from Schema.

object schema do not have any default transforms applied.

Object schema come with a default value already set, which "builds" out the object shape, a sets any defaults for fields:

This may be a bit surprising, but is usually helpful since it allows large, nested schema to create default values that fill out the whole shape and not just the root object. There is one gotcha! though. For nested object schema that are optional but include non optional fields may fail in unexpected ways:

This is because yup casts the input object before running validation which will produce:

During the validation phase names exists, and is validated, finding names.first missing. If you wish to avoid this behavior do one of the following:

Define the keys of the object and the schemas for said keys.

Note that you can chain shape method, which acts like Object.assign.

would be exactly the same as:

Attempt to parse input string values as JSON using JSON.parse.

Creates a object schema, by applying all settings and fields from schemaB to the base, producing a new schema. The object shape is shallowly merged with common fields from schemaB taking precedence over the base fields.

Create a new schema from a subset of the original's fields.

Create a new schema with fields omitted.

Transforms the specified key to a new key. If alias is true then the old key will be left.

Validate that the object value only contains keys specified in shape, pass false as the first argument to disable the check. Restricting keys to known, also enables stripUnknown option, when not in strict mode.

Isha Mara