Schemas
array
Parses any iterable to an array.
const schema = x.array(x.string)
assert.deepEqual(schema.parse(['a']).value, ['a'])
assert.deepEqual(schema.parse(new Set(['a'])).value, ['a'])
assert(schema.parse([1]).success === false)
assert(schema.parse(1).success === false)
assert(schema.parse({}).success === false)
Access the array content schema with .item
const schema = x.array(x.string)
assert(schema.item === x.string)
bigint
It accepts any input that can construct a BigInt. You can use it to decode JSON coming from a JSON.parse
assert.deepEqual(x.bigint.parse(1), { success: true, value: 1n })
assert.deepEqual(x.bigint.parse('1'), { success: true, value: 1n })
assert.deepEqual(x.bigint.parse(1n), { success: true, value: 1n })
assert.deepEqual(x.bigint.parse(true), { success: true, value: 1n })
assert(x.bigint.parse(1.54).success === false)
assert(x.bigint.parse(1.23).success === false)
assert(x.bigint.parse({}).success === false)
boolean
const schema = x.boolean
assert(x.boolean.parse(true).success === true)
assert(x.boolean.parse(false).success === true)
assert(x.boolean.parse(1).success === false)
assert(x.boolean.parse('toto').success === false)
date
It can parse anything the Date
constructor can take as single parameter.
If you need to accept Date
only, use x.instanceOf(Date)
const schema = x.dat e
parses a Date
const now = new Date()
assert.deepEqual(x.date.parse(now), { success: true, value: now })
parses a string
const a = '2021-01-02T03:04:05.123Z'
assert.deepEqual(x.date.parse(a), { success: true, value: new Date(a) })
const b = '2021-01-02'
assert.deepEqual(x.date.parse(b), { success: true, value: new Date(b) })
assert(x.date.parse('oopsie').success === false)
parses a number
const timestamp = Date.now()
assert.deepEqual(x.date.parse(timestamp), {
success: true,
value: new Date(timestamp),
})
assert(x.date.parse(NaN).success === false)
assert(x.date.parse(() => {}).success === false)
Enum
Parses as-const enum
const Direction = { Left: 'Left', Right: 'Right' } as const
const schema = x.Enum(Direction)
assert(schema.parse('Left').success === true)
assert(schema.parse('Left').value === Direction.Left)
assert(schema.parse('Letf').success === false)
Parses an enum with values
enum Direction {
Left = 'Left',
Right = 'Right',
}
const schema = x.Enum(Direction)
assert(schema.parse('Left').success === true)
assert(schema.parse('Left').value === Direction.Left)
assert(schema.parse('Letf').success === false)
Parses an enum without values
enum Direction {
Left,
Right,
}
const schema = x.Enum(Direction)
assert(schema.parse(0).success === true)
assert(schema.parse(0).value === Direction.Left)
assert(schema.parse(-1).success === false)
instanceOf
parsing a Date
const schema = x.instanceOf(Date)
assert(schema.parse(new Date()).success === true)
parsing a custom User
class
class User {}
const schema = x.instanceOf(User)
assert(schema.parse(new User()).success === true)
integer
it accepts anything passing the check Number.isSafeInteger
.
assert(x.integer.parse(42).success === true)
assert(x.integer.parse(-42).success === true)
assert(x.integer.parse(31.2).success === false)
assert(x.integer.parse(Infinity).success === false)
assert(x.integer.parse(NaN).success === false)
assert(x.integer.parse(1e100).success === false)
assert(x.integer.parse(true).success === false)
assert(x.integer.parse('abc').success === false)
literal
const schema = x.literal('a', 42, true, null, undefined)
assert(schema.parse('a').value === 'a')
assert(schema.parse(42).value === 42)
assert(schema.parse(true).value === true)
assert(schema.parse(null).value === null)
assert(schema.parse(undefined).value === undefined)
assert(schema.parse('b').success === false)
assert(schema.parse(43).success === false)
assert(schema.parse(false).success === false)
mapOf
const schema = x.mapOf(x.number, x.string)
const entries = [
[1, 'Jack'],
[2, 'Mary'],
]
const map = new Map(entries)
assert.deepEqual(
schema.parse(entries), // it parses entries
{ success: true, value: map },
)
assert.deepEqual(
schema.parse(map), // it parses a map
{ success: true, value: map },
)
assert(schema.parse([['1', 'Jack']]).success === false)
assert(schema.parse([['Jack', 1]]).success === false)
number
This schema only accepts finite numbers for safety.
If you need full control over your number, use unsafeNumber
instead.
Basically, it accepts anything passing the check Number.isFinite
.
assert(x.number.parse(1).success === true)
assert(x.number.parse(-1.12).success === true)
assert(x.number.parse(Infinity).success === false)
assert(x.number.parse(NaN).success === false)
assert(x.number.parse(true).success === false)
assert(x.number.parse('abc').success === false)
object
const person = x.object({ name: x.string })
assert(person.parse({ name: 'Jack' }).success === true)
assert(person.parse({ name: 42 }).success === false)
it parses null prototype objects
const schema = x.object({ n: x.number })
const a = Object.create(null)
a.n = 1
assert(schema.parse(a).success === true)
assert(schema.parse({ __proto__: null, n: 1 }).success === true)
assert(schema.parse([]).success === false)
assert(schema.parse('abc').success === false)
assert(schema.parse(42).success === false)
assert(schema.parse(new Set()).success === false)
assert(schema.parse(new Map()).success === false)
record
const schema = x.record(x.string.convertTo(x.number, Number), x.string)
assert.deepEqual(schema.parse({ 42: 'hello' }), {
success: true,
value: { 42: 'hello' },
})
assert(schema.parse({ hello: 42 }).success === false)
assert(schema.parse({ hello: 'world' }).success === false)
failures
const schema = x.record(x.string, x.number)
assert(schema.parse([]).success === false)
assert(schema.parse(new Set()).success === false)
assert(schema.parse(new Map()).success === false)
assert(schema.parse({ 1: '12' }).success === false)
setOf
Parses any iterable to an array.
const schema = x.setOf(x.string)
assert.deepEqual(schema.parse(['a']).value, new Set(['a']))
assert.deepEqual(schema.parse(new Set(['a'])).value, new Set(['a']))
assert(schema.parse([1]).success === false)
assert(schema.parse(1).success === false)
assert(schema.parse({}).success === false)
Access the Set content schema with .item
const schema = x.setOf(x.string)
assert(schema.item === x.string)
string
This also trims the string. If you do not want this behavior, explicitly use
assert(x.string.parse(' hello ').value === 'hello')
tuple
const schema = x.tuple(x.string, x.number)
assert.deepEqual(schema.parse(['a', 1]), { success: true, value: ['a', 1] })
assert.deepEqual(schema.parse(['a', 1, 2, 3, 4, 5]), {
success: true,
value: ['a', 1],
})
assert(schema.parse([1, 2]).success === false)
assert(schema.items[0] === x.string)
assert(schema.items[1] === x.number)
failures
const schema = x.tuple(x.string, x.number)
assert(schema.parse(['1']).success === false)
assert(schema.parse(new Set(['1', 2])).success === false)
assert(schema.parse(new Map()).success === false)
assert(schema.parse({ 0: '1', 1: 2 }).success === false)
assert(schema.parse({ 0: '1', 1: 2, length: 2 }).success === false)
union
If you want to use a discriminated union, checkout
const schema = x.union(x.string, x.number)
assert(schema.parse('a').value === 'a')
assert(schema.parse(42).value === 42)
assert(schema.parse({}).success === false)
variant
If you need to use a simple union, checkout
const a = x.object({ type: x.literal('a'), a: x.string })
const b = x.object({ type: x.literal('b'), b: x.number })
const schema = x.variant('type', [a, b])
assert.deepEqual(schema.parse({ type: 'a', a: 'Hello' }), {
success: true,
value: { type: 'a', a: 'Hello' },
})
assert.deepEqual(schema.parse({ type: 'b', b: 42 }), {
success: true,
value: { type: 'b', b: 42 },
})
assert(schema.name === 'a | b')