Decoder<T>
The Decoder class represents a type-safe decoder that validates and transforms untrusted data
The Decoder<T> class is the core abstraction in the decoders library. It represents a
reusable, composable decoder that can validate and transform untrusted input data into
typed values.
Decoding Methods
.verify()
Method .verify( blob: unknown ): T (source)
Method .verify( blob: unknown, formatter: Formatter ): T
Validates an input value. Returns the decoded value or throws.
| Input | Result |
|---|---|
| 123 | |
| 3.1415 | |
| "hello" ^^^^^^^ Must be number |
.value()
Method .value( blob: unknown ): T | undefined (source)
Validates an input value. Returns the decoded value or return undefined. Never throws.
| Input | Result |
|---|---|
| 3 | |
| undefined | |
| 42 | |
| undefined |
.decode()
Method .decode( blob: unknown ): DecodeResult<T> (source)
Validates an input value. Returns a DecodeResult type. Never throws.
type DecodeResult<T> =
| { ok: true; value: T }
| { ok: false; error: Annotation };In case of error, an Annotation will be returned, which is a structured "copy" of the
input value with annotations inlined on the rejected parts. Typically you will want to
call formatInline or formatShort on this. See
Error Formatting.
number.decode(3); // { ok: true, value: 3 }
number.decode('hi'); // { ok: false, error: ... }Best practices
| Method | Returns | On failure | When to use? |
|---|---|---|---|
.verify() | T | Throws | You want to just fail fast. |
.value() | T | Returns undefined | You have sensible defaults. |
.decode() | DecodeResult<T> | Returns full details | You need fine-grained error handling. |
Transformation Methods
.transform()
Method .transform( transformFn: (T) => V ): Decoder<V> (source)
Builds a new decoder that transforms the decoded value using a function.
| Input | Result |
|---|---|
| "FOO" | |
| "HELLO, WORLD!" | |
| 4 ^ Must be string |
.refine()
Method .refine( predicate: T => boolean, message: string ): Decoder<T> (source)
Adds an extra condition. Rejects values that don't match the predicate.
| Input | Result |
|---|---|
| 3 | |
| 42 ^^ Must be odd | |
| "hi" ^^^^ Must be number |
.refineType()
Method .refineType( ): Decoder<SubT> (source)
Available since 2.7.
Narrows the return type to a subtype. Useful for branded types. No runtime effect.
const user = object({ name: string }).refineType<Person>();.reject()
Method .reject( rejectFn: T => string | null ): Decoder<T> (source)
Like .refine(), but lets you return a dynamic error message. Return null to
accept, or a string to reject.
| Input | Result |
|---|---|
| "hello" | |
| "this string is too long" ^^^^^^^^^^^^^^^^^^^^^^^^^ Too long (23 chars) | |
| 42 ^^ Must be string |
.describe()
Method .describe( message: string ): Decoder<T> (source)
Overrides the error message when the decoder rejects.
| Input | Result |
|---|---|
| "a" | |
| "x" ^^^ Must be a vowel | |
| 42 ^^ Must be a vowel |
Composition Methods
.then()
.then() was renamed to .chain() in 2.9 to avoid being mistaken for a Promise.
.chain()
Method .chain( next: (blob: T, ok, err) => DecodeResult<V> | Decoder<V> ): Decoder<V>
Method .chain( next: Decoder<V> ): Decoder<V> (source)
Low-level method to send decoded output into another decoder or acceptance function.
Prefer .transform(), .refine(), or .pipe() in most cases.
.pipe()
Method .pipe( next: Decoder<V> ): Decoder<V> (source)
Method .pipe( next: (blob: T) => Decoder<V> ): Decoder<V>
Available since 2.4.
Sends the decoded output into another decoder for further validation.
| Input | Result |
|---|---|
| [7] | |
| [1, 2, 3] | |
| [ 1, -3, ^^ Number must be positive (at index 1) ] | |
| [ NaN, ^^^ Number must be finite (at index 0) ] | |
| [ 3.14, ^^^^ Number must be an integer (at index 0) ] | |
| 123 ^^^ Must be string | |
| true ^^^^ Must be string | |
| null ^^^^ Must be string |
Dynamic decoder selection
You can also use .pipe() to dynamically select a decoder based on the input value.
| Input | Result |
|---|---|
| [ 1, ] ^ Must be 2D or 3D point | |
| [1, 2] | |
| [1, 2, 3] | |
| [ 1, 2, 3, 4, ] ^ Must be 2D or 3D point |
Inferring the type of a Decoder
Extracts the output type from a Decoder. Other libraries call this "infer".
import type { DecoderType } from 'decoders';
import { array, number, object, string } from 'decoders';
const tagsDecoder = array(string);
const personDecoder = object({
name: string,
age: number,
});
type Tags = DecoderType<typeof tagsDecoder>;
// string[]
type Person = DecoderType<typeof personDecoder>;
// { name: string; age: number }