Skip to content

oneOf()

ts
function oneOf<T>(...parsers): Parser<T[number]>

Executes parsers in order and returns the first successful parsing attempt, or a failure if all fail. Use it to parse unions, to parse data that comes in different shape, and to provide fallbacks for failed parsing attempts.

See

withDefault for a shorthand for fallback with a static value.

Type Parameters

Type Parameter
T extends readonly unknown[]

Parameters

ParameterTypeDescription
...parsers{ [K in string | number | symbol]: Parser<T[K<K>]> }A list of parsers to be called in order.

Returns

Parser<T[number]>

A parser function that will call the parsers in parsers in order and return the result of the first successful parsing attempt, or a failure if all parsing attempts fail.

Examples

Parse unions:

ts
const parseNumberOrString = oneOf(parseNumber, parseString)
parseNumberOrString(0) // => ParseSuccess<number | string>
parseNumberOrString('abc') // => ParseSuccess<number | string>
parseNumberOrString(null) // => ParseError

Parse discriminated unions:

ts
const parseResult = oneOf(
  object({
    tag: equals('success')
    value: parseString
  }),
  object({
    tag: equals('error')
  }),
)

Provide fallbacks for failed parsing attempts; for example, parse a number from data that is either a number or a stringified number:

ts
const parseStrOrNum = fallback([parseNumber, parseNumberFromString])
parseStrOrNum(2) // -> { tag: 'success', value: 2 }
parseStrOrNum('2') // -> { tag: 'success', value: 2 }

(Do not encode data like this when there's a choice; but sometimes, existing data comes in weird shapes and forms.)

Provide a static default value when parsing fails:

ts
const parseName = oneOf([
  parseString,
  () => success('Anonymous')
])

You can also use withDefault for this use case.

When explicitly annotating oneOf, provide a tuple as type argument:

ts
type Success = {
  tag: 'success'
  value: string
}
type Failure = {
  tag: 'failure'
}
type Result = Success | Failure
const parseLogLevel = equals<[Success, Failure]>(
 object({
   tag: equals('success')
   value: parseString
 }),
 object({
   tag: equals('error')
 }),
)

Due to a limitation of TypeScript, it is not possible to write oneOf<string | number>(). Therefore, it is generally recommended to omit the type arguments for oneOf and let TypeScript infer them.