drytype
DryType is a runtime type-validation library with TypeScript in mind.
Runtime type validations are performed with a runtime type -- a DryType
as
I've called it throughout this library (beats me why).
A DryType is an object of the type:
export type DryType<T> = {
validate(param: unknown): ValidationResult;
// will throw if check fails
strictValidate(
param: unknown,
): ValidationResult;
guard(param: unknown): param is T;
// will throw if check fails
strictGuard(param: unknown): param is T;
toString(): string;
intersect<S>(dt: DryType<S>): DryType<T & S>;
/*
errorFrom refers to whether the error from the
first type, second type, or the default one is
to be thrown.
when this is 0 or undefined, the default error is used
when this is 1, the 'left' error is used
when this is 2 (or any other value), the 'right' error is used
*/
union<S>(dt: DryType<S>, errorFrom?: number): DryType<T | S>;
tag: string;
};
type ValidationResult = {
success: boolean;
message?: string;
in?: string;
};
Might look fancy, but it's actually pretty simple.
validate(param: unknown)
is used to check if a value param
confirms to the
type specification of that DryType
, for example
import { String } from "drytype";
String.validate("hello"); // { success: true }
String.validate(20); // { success: false, message: "expected: string, got: number" }
strictValidate
is the same as validate
, with one big difference: when the
validation fails, instead of returning a ValidationResult object, it throws a
ValidationError(message)`.
guard
and strictGuard
are the same as validate
and strictValidate
, with
the difference being that they are TypeScript guards instead of regular boolean
returning functions.
union
is the same as TypeScript |
. A.union(B)
returns a new DryType, which
now checks if either A or B succeed. For example,
import { Number, String } from "drytype";
String.union(Number).validate(10); // { success: true }
union
also takes a second parameter called fromError, which is used when both
checks fail. If this is set to 0 or undefined, the default error will be used.
If this is set to 1, the custom error from the DryType on the left will be used,
if any. Any other value will make it use the custom error from the DryType on
the right, if any.
intersect
is the same as TypeScript &
. A.intersect(B)
returns a new
DryType, which now checks if both A and B succeed. For example,
import { NumberGreaterThan, NumberLessThan } from "drytype";
// a number between between 5 and 10
NumberGreaterThan(5).intersect(NumberLessThan(10)).validate(7); // { success: true }
That covers what a DryType is composed of. A set of useful DryTypes have been provided by default in the modules directory for convenience. However, creating a new DryType is also very easy.
To create a new DryType, you can use makeDryType
, which has the type:
const makeDryType = <T>(
validator: (x: unknown) => ValidationResult,
tag = "unknown",
): DryType<T>
Here's an example:
export const Function = makeDryType<Function>(
(x) => typeof x == "function" ? { success: true } : { success: false },
"function",
);
The generic type parameter is the type that the validated value should be of.
This is used for TypeScript guards. The first parameter is a function that takes
x: unknown
and validates it. This function has to return a ValidationResult
object, where success: boolean
is a compulsory field. The message
field will
never be used if success
is true
, so you can skip it if success
is true
.
However, if success
is false
, and you still skip the message
field, a
default message will be used, which is:
`expected: ${drytypeInQuestion.tag}, got: ${typeof (unknownParam)}${
result.in == undefined ? "" : `, in: ${result.in}`
}`;
The only use of the in
parameter in ValidationResult
is to be inserted this
way into the default error message. This can be useful for, say, Records where
you need to give out additional information about where the validation failed.
NOTE: Also have a look at the tests for an example usage. Every provided DryType has at least one test present.
That's all you need to know to use this library. Happy validatin'!