Utilities
Utility decoders for custom logic, preprocessing, and advanced use cases.
unknown
unknown: Decoder<unknown> (source)
anything: Decoder<unknown> alias
Accepts anything and returns it unchanged.
Useful for situation in which you don't know or expect a specific type. Of course, the downside is that you won't know the type of the value statically and you'll have to further refine it yourself.
| Input | Result |
|---|---|
| "hello" | |
| false | |
| undefined | |
| [1, 2] |
always
function always( value: T ): Decoder<T> (source)
function always( value: () => T ): Decoder<T>
Accepts any input, ignores it, and instead returns the provided value instead.
This is useful to manually add extra fields to object decoders.
| Input | Result |
|---|---|
| 42 | |
| 42 | |
| 42 |
Or use it with a function instead of a constant:
| Input | Result |
|---|---|
| "0.27" | |
| "0.69" |
never
never: Decoder<never> (source)
fail: Decoder<never> alias
Rejects all inputs, and always fails with the given error message. May be useful for explicitly disallowing keys, or for testing purposes.
| Input | Result |
|---|---|
| "hello" ^^^^^^^ Computer says no | |
| 42 ^^ Computer says no | |
| true ^^^^ Computer says no | |
| null ^^^^ Computer says no | |
| undefined ^^^^^^^^^ Computer says no |
instanceOf
function instanceOf( klass: Klass<T> ): Decoder<T> (source)
Accepts any value that is an instanceof the given class.
| Input | Result |
|---|---|
| Error { "foo" } | |
| "foo" ^^^^^ Must be Error instance | |
| 3 ^ Must be Error instance |
lazy
function lazy( decoderFn: () => Decoder<T> ): Decoder<T> (source)
Lazily evaluate the given decoder. Useful to build recursive decoders.
| Input | Result |
|---|---|
| … | |
| { "value": "root", } ^ Missing key: 'children' | |
| "not a tree" ^^^^^^^^^^^^ Must be an object |
sized
function sized( decoder: Decoder<string>, options: SizeOptions ): Decoder<string> (source)
function sized( decoder: Decoder<T[]>, options: SizeOptions ): Decoder<T[]>
function sized( decoder: Decoder<Set<T>>, options: SizeOptions ): Decoder<Set<T>>
Available since 2.9.
Rejects strings, arrays, or sets that don't match the given size constraints. Works on any
type that has a .length or .size property.
type SizeOptions =
| { size: number }
| { min: number; max?: number }
| { min?: number; max: number };For strings, error messages refer to "chars". For arrays and sets, error messages refer to "items".
| Input | Result |
|---|---|
| "hello" | |
| "hi" | |
| "x" ^^^ Too short, must be at least 2 chars | |
| "this string is too long" ^^^^^^^^^^^^^^^^^^^^^^^^^ Too long, must be at most 10 chars | |
| 42 ^^ Must be string |
define
function define( fn: (blob: unknown, ok, err) => DecodeResult<T> ): Decoder<T> (source)
Defines a new Decoder<T>, by implementing a custom acceptance function. The function
receives three arguments:
blob- the raw/unknown input (aka your external data)ok- Callok(value)to accept the input and returnvalueerr- Callerr(message)to reject the input with errormessage
The expected return value should be a DecodeResult<T>, which can be obtained by
returning the result of calling the provided ok or err helper functions. Please note
that ok() and err() don't perform side effects! You'll need to return those values.
You probably don't need this!
This is the lowest-level API to define a new decoder, and not recommended unless you
have no alternative. In almost all cases starting from an existing decoder and using
.transform() or .refine() will be preferable.
//
// NOTE: This example just shows how define() works.
// Please do NOT implement an uppercase decoder like this! 🙈
//
const uppercase = define<string>((blob, ok, err) => {
if (typeof blob === 'string') {
// Accept the input
return ok(blob.toUpperCase());
} else {
// Reject the input
return err('Must be string');
}
});// 👍
uppercase.verify('hi there') === 'HI THERE';
// 👎
uppercase.verify(123); // throws: Must be stringprep
function prep( mapperFn: (raw: unknown) => unknown, decoder: Decoder<T> ): Decoder<T> (source)
Pre-process the data input before passing it into the decoder. This gives you the ability
to arbitrarily customize the input on the fly before passing it to the decoder. Of course,
the input value at that point is still of unknown type, so you will have to deal with
that accordingly.
const decoder = prep(
// Will convert any input to an int first, before feeding it to
// positiveInteger. This will effectively also allow numeric strings
// to be accepted (and returned) as integers. If this ever throws,
// then the error message will be what gets annotated on the input.
(x) => parseInt(x),
positiveInteger,
);
// 👍
decoder.verify(42) === 42;
decoder.verify('3') === 3;
// 👎
decoder.verify('-3'); // throws: not a positive number
decoder.verify('hi'); // throws: not a number