Validator is a standard API for validation.
The Validator is the following interface:
interface Validator<In = unknown, RIn extends In = In> {
/** Validates the input and yield validation errors if exists. */
validate: (input: In) => Iterable<ValidationFailure>;
/** Whether the input is valid or not. */
is: (input: In) => input is RIn;
}
/** Validation failure. */
interface ValidationFailure {
/** The validation failure message. */
message: string;
/** The path to a part of the instance. */
instancePath: PropertyKey[];
}Generics In represents the tolerance of the validator.
Generics RIn is the type of the refinement by narrowing. That is, it
represents a Refined In.
Thus, Validator<In, RIn> is expressed as "a validator that accepts In and
guarantees that it is RIn if validation succeeds.
Due to type system expressivity constraints, RIn may be the same as In.
validate performs validation and can report a ValidationFailure. Iterable
indicates that it is lazy executable.
The absence of any ValidationFailure indicates that the validation was
successful.
ValidationFailure can provide the reason why the validation failed and
information about the target. Currently, only instance paths are standardized.
The is exists primarily for type narrowing. See
FAQ: Why Validator needs is implement
for why this is necessary.
Validators are very simple and easy to define.
import type {
ValidationFailure,
Validator,
} from "https://deno.land/x/abstruct@$VERSION/mod.ts";
const StringValidator: Validator<unknown, string> = {
*validate(input: unknown): Iterable<ValidationFailure> {
if (!this.is(input)) {
yield {
message: `should be string, actual ${typeof input}`,
instancePath: [],
};
}
},
is(input: unknown): input is string {
return typeof input === "string";
},
};Of course, helpers are available, but it is worthwhile to know how to define them in a pure way.
You will want to define only one of the two required methods.
The essential function of Validator is validate. Here is how to define a
validator from a validate.
Class style:
import {
BasicValidator,
type ValidationFailure,
} from "https://deno.land/x/abstruct@$VERSION/mod.ts";
class StringItemValidator
extends BasicValidator<Iterable<unknown>, Iterable<string>> {
*validate(input: Iterable<unknown>): Iterable<ValidationFailure> {
let i = 0;
for (const item of input) {
if (typeof item !== "string") {
yield {
message: `should be string, actual ${typeof input}`,
instancePath: [i++],
};
}
}
}
}Function style:
import { defineValidator } from "https://deno.land/x/abstruct@$VERSION/mod.ts";
const StringItemValidator = defineValidator<
Iterable<unknown>,
Iterable<string>
>(function* (input) {
let i = 0;
for (const item of input) {
if (typeof item !== "string") {
yield {
message: `should be string, actual ${typeof input}`,
instancePath: [i++],
};
}
}
});For validators that target a single value, you will want to define the validator
from the is function rather than from the validate.
However, is is not very expressive of validation failure, so the following
interface is defined.
interface Checker<In> {
check: (input: In) => true | string;
}If check is true, the validation represents success. And string represents
a failure and the reason for the failure.
Class style:
import { ScalarValidator } from "https://deno.land/x/abstruct@$VERSION/mod.ts";
class StringValidator extends ScalarValidator<unknown, string> {
check(input: unknown): true | string {
const typeOf = typeof input;
return typeOf === "string" || `should be string, actual ${typeOf}`;
}
}Functional style:
import { defineScalarValidator } from "https://deno.land/x/abstruct@$VERSION/mod.ts";
const StringValidator = defineScalarValidator<unknown, string>((input) => {
const typeOf = typeof input;
return typeOf === "string" || `should be string, actual ${typeOf}`;
});The following is a list of standard validators.
In indicates the broadest type accepted. Most validators have generics and will do narrowing, but check the implementation.
| Name | In |
|---|---|
| EnumValidator | unknown |
| NullishValidator | unknown |
| RangeValidator | unknown |
| PatternValidator | string |
| AndValidator | unknown |
| EqualityValidator | unknown |
| InequalityValidator | unknown |
| GreaterThanValidator | unknown |
| GreaterThanOrEqualValidator | unknown |
| LessThanValidator | unknown |
| LessThanOrEqualValidator | unknown |
| InstanceValidator | unknown |
| NotValidatorValidator | unknown |
| OrValidatorValidator | unknown |
| TypeValidator | unknown |
| PropertiesValidator | Record<PropertyKey, unknown> |
| OptionalValidator | Partial<Record<PropertyKey, unknown>> |
| PropertyValueValidator | Record<string, unknown> |
| PropertyKeyValidator | object |
| NegativeNumberValidator | number | bigint |
| NonNegativeNumberValidator | number | bigint |
| NonPositiveNumberValidator | number | bigint |
| PositiveNumberValidator | number | bigint |
| FloatValidatorValidator | number |
| IntegerValidator | number |
| EmptyValidator | Iterable<unknown> |
| NonEmptyValidator | Iterable<unknown> |
| ItemValidator | Iterable<unknown> |
| CountValidator | Iterable<unknown> |
| MaxCountValidator | Iterable<unknown> |
| MinCountValidator | Iterable<unknown> |
| SingleValidator | Iterable<unknown> |
| UniqueValidator | Iterable<unknown> |
| ValidDateValidator | Date |
| FixedArrayValidator | unknown[] |