Skip to main content
Version: v2

AnyOf

Describes a union of types, i.e. a range of possible types:

import { anyOf } from 'dynamodb-toolbox/schema/anyOf'

const pokeTypeSchema = anyOf(
string().const('fire'),
string().const('grass'),
string().const('water')
)

type PokeType = FormattedValue<typeof pokeTypeSchema>
// => 'fire' | 'grass' | 'water'

In this example, an enum would have done the trick. However, anyOf becomes particularly powerful when used in conjunction with a map and the enum or const directives of a primitive attribute, to implement polymorphism:

const captureSchema = anyOf(
map({
status: string().const('caught'),
// 👇 captureState.trainerId exists if status is "caught"...
trainerId: string()
}),
// ...but not otherwise! 🙌
map({ status: string().const('wild') })
)

type Capture = FormattedValue<typeof captureSchema>
// =>
// | { status: "caught"; trainerId: string }
// | { status: "wild" }
warning

Parsing an anyOf attribute value returns the parsed output of the first sub-schema it validates against.

This means the order of the sub-schemas matters: you should always start with the strictest schemas.

info

For the moment, anyOf properties can only be set by using methods.

AnyOf elements can have any type. However, they must respect some constraints:

  • They cannot be optional or always required
  • They cannot be hidden or key (tagging the record itself as key is enough)
  • They cannot have default or links
// ❌ Raises a type AND a run-time error
const union = anyOf(number(), string().optional())
const union = anyOf(number(), string().hidden())
const union = anyOf(number(), string().key())
const union = anyOf(number(), string().default('foo'))

Properties

.required()

string | undefined

Tags schema values as required (within items or maps). Possible values are:

  • 'atLeastOnce' (default): Required (starting value)
  • 'always': Always required (including updates)
  • 'never': Optional
const pokeTypeSchema = anyOf(
string().const('fire'),
string().const('grass'),
string().const('water')
).required()

// shorthand for `.required('never')`
const pokeTypeSchema = anyOf(...).optional()

.hidden()

boolean | undefined

Omits schema values during formatting:

const pokeTypeSchema = anyOf(
string().const('fire'),
string().const('grass'),
string().const('water')
).hidden()

.key()

boolean | undefined

Tags schema values as a primary key attribute or linked to a primary key attribute:

// Note: The method also sets the `required` property to 'always'
// (it is often the case in practice, you can still use `.optional()` if needed)
const pokeTypeSchema = anyOf(
string().const('fire'),
string().const('grass'),
string().const('water')
).key()

.savedAs(...)

string

Renames schema values during the transformation step (within items or maps):

const pokeTypeSchema = anyOf(
string().const('fire'),
string().const('grass'),
string().const('water')
).savedAs('pkt')

.default(...)

ValueOrGetter<ATTRIBUTES>

Specifies default values. See Defaults and Links for more details:

Examples
const now = () => new Date().toISOString()

const hasUpdateSchema = anyOf(
map({ hasUpdate: boolean().const(false) }),
map({ hasUpdate: boolean().const(true), date: string() })
)
.default(() => ({ hasUpdate: false }))
.updateDefault(() => ({ hasUpdate: true, date: now() }))
// 👇 Similar to
const timestampsSchema = anyOf('...')
.putDefault(() => ({ hasUpdate: false }))
.updateDefault(() => ({ hasUpdate: true, date: now() }))

.link<Schema>(...)

Link<SCHEMA, ELEMENTS>

Similar to .default(...) but allows deriving the default value from other attributes. See Defaults and Links for more details:

const pokemonSchema = item({
name: string().optional(),
level: number()
}).and(prevSchema => ({
metadata: anyOf(string(), number()).link<
typeof prevSchema
>(
// 🙌 Correctly typed!
({ name, level }) => name ?? level
)
}))

.validate(...)

Validator<ELEMENTS>

Adds custom validation. See Custom Validation for more details:

Examples
const nonEmptyListSchema = anyOf(
list(string()),
list(number())
).validate(input => input.length > 0)
// 👇 Similar to
const nonEmptyListSchema = anyOf(
list(string()),
list(number())
).putValidate(input => input.length > 0)