decoders

Objects

Object decoders for validating structured data.

Object shapes

object

function object(
  { field1: Decoder<A>, field2: Decoder<B>, ... }
): Decoder<{ field1: A, field2: B, ... }> (source)

Accepts objects with fields matching the given decoders. Extra fields that exist on the input object are ignored and will not be returned.

Try it
object({ x: number, y: number }).verify(input)
InputResult
{ "x": 1, "y": 2 }
{ "x": 1, "y": 2 }
{ "x": 1, } ^ Missing key: 'y'

Read more here about the differences between object, exact, and inexact.


exact

function exact(
  { field1: Decoder<A>, field2: Decoder<B>, ... }
): Decoder<{ field1: A, field2: B, ... }> (source)

A "strict object" decoder. Like object(), but will reject inputs that contain extra fields that are not specified explicitly.

Try it
exact({ x: number, y: number }).verify(input)
InputResult
{ "x": 1, "y": 2 }
{ "x": 1, "y": 2, "z": 3, } ^ Unexpected extra keys: 'z'
{ "x": 1, } ^ Missing key: 'y'

Read more here about the differences between object, exact, and inexact.


inexact

function inexact(
  { field1: Decoder<A>, field2: Decoder<B>, ... }
): Decoder<{ field1: A, field2: B, ... }> (source)

A "loose object" decoder. Like object(), but will pass through any extra fields on the input object unvalidated that will thus be of unknown type statically.

Try it
inexact({ x: number, y: number }).verify(input)
InputResult
{ "x": 1, "y": 2 }
{ "x": 1, "y": 2, "z": 3 }
{ "x": 1, } ^ Missing key: 'y'

Read more here about the differences between object, exact, and inexact.


What's the difference?

The three decoders in the "object" family are very similar and differ only in how they treat extra properties on input values.

Try it
const fields = {  x: number,  y: number,};object(fields).verify(input)exact(fields).verify(input)inexact(fields).verify(input)
Inputobjectexactinexact
{ "x": 1, "y": 2 }{ "x": 1, "y": 2, "z": 3, } ^ Unexpected extra keys: 'z'{ "x": 1, "y": 2, "z": 3 }
{ "x": 1, "y": 2 }{ "x": 1, "y": 2 }{ "x": 1, "y": 2 }

Dictionary shapes

record

function record( values: Decoder<V> ): Decoder<Record<string, V>> (source)
function record( keys: Decoder<K>, values: Decoder<V> ): Decoder<Record<K, V>>

Accepts objects where all values match the given decoder, and returns the result as a Record<string, V>.

This is useful to validate inputs like { [key: string]: V }.

Decoding values only

The default call takes a single argument and will validate all values. For example, to validate that all values in the object are numbers:

Try it
record(number).verify(input)
InputResult
{ "red": 1, "blue": 2, "green": 3 }
{ "hi": "not a number", ^^^^^^^^^^^^^^ Must be number }

Decoding keys and values

If you also want to validate that keys are of a specific form, use the two-argument form: record(key, value). Note that the given key decoder must return strings.

For example, to enforce that all keys are emails:

Try it
record(email, number).verify(input)
InputResult
{ "me@nvie.com": 1 }
{ "no-email": 1, } ^ Invalid key 'no-email': Must be email

Simple objects

pojo

pojo: Decoder<Record<string, unknown>> (source)

Accepts any "plain old JavaScript object", but doesn't validate its keys or values further.

Try it
pojo.verify(input)
InputResult
{}
{ "name": "hi" }
"hi" ^^^^ Must be an object
[] ^^ Must be an object
new Date('2026-03-18T07:22:58.146Z') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Must be an object
null ^^^^ Must be an object

On this page