Skip to main content

Validator<T>

The type accepted by RequestConfig.validate for runtime response validation.

type Validator<T> =
| ((input: unknown) => T)
| { parse(input: unknown): T }
| StandardSchemaV1<unknown, T>

Accepted shapes

parcely checks the validator in this order at runtime:

ShapeDetectionExamples
Standard Schema v1Has a ~standard propertyZod 3.24+, Valibot 1+, ArkType 2+, Effect-Schema
.parse() objectHas a parse methodZod (all versions), custom adapters
Plain functionIs callable(input: unknown) => T

StandardSchemaV1

parcely includes a type-only definition of the Standard Schema v1 interface. No runtime dependency is needed.

interface StandardSchemaV1<Input = unknown, Output = Input> {
readonly '~standard': {
readonly version: 1
readonly vendor: string
readonly validate: (
value: unknown,
) => StandardSchemaV1.Result<Output> | Promise<StandardSchemaV1.Result<Output>>
readonly types?: {
readonly input: Input
readonly output: Output
}
}
}

Sub-types

The StandardSchemaV1 namespace includes these supporting types:

namespace StandardSchemaV1 {
type Result<Output> = SuccessResult<Output> | FailureResult

interface SuccessResult<Output> {
readonly value: Output
readonly issues?: undefined
}

interface FailureResult {
readonly issues: ReadonlyArray<Issue>
}

interface Issue {
readonly message: string
readonly path?: ReadonlyArray<PropertyKey | PathSegment>
}

interface PathSegment {
readonly key: PropertyKey
}
}

ValidatorOutput<V>

Conditional helper type that extracts the parsed-output type from any validator shape. The Client method overloads use this internally so calls like http.get('/u', { validate: schema }) infer data from the schema with no explicit <T>. You can also use it directly when wrapping parcely:

import type { ValidatorOutput, Validator } from '@parcely/core'

type FromZod = ValidatorOutput<typeof UserSchema> // z.infer<typeof UserSchema>
type FromParse = ValidatorOutput<{ parse(i: unknown): User }> // User
type FromFn = ValidatorOutput<(i: unknown) => User> // User
type Fallback = ValidatorOutput<unknown> // unknown

Resolution order (Standard Schema first because Zod 3.24+ implements both):

  1. StandardSchemaV1<unknown, infer Out>Out
  2. { parse(input: unknown): infer Out }Out
  3. (input: unknown) => infer OutOut
  4. otherwise → unknown

Error behaviour

When validation fails, parcely throws HttpError with:

  • code: 'ERR_VALIDATION'
  • response: the original HttpResponse envelope
  • cause: the error thrown by the validator

Example

import { createClient } from '@parcely/core'
import { z } from 'zod'

const http = createClient({ baseURL: 'https://api.example.com' })

// Standard Schema (Zod 3.24+)
const User = z.object({ id: z.string(), name: z.string() })
await http.get('/users/me', { validate: User })

// .parse() object
await http.get('/users/me', { validate: { parse: (d) => d as { id: string } } })

// Plain function
await http.get('/users/me', {
validate: (d: unknown) => {
if (typeof d === 'object' && d !== null && 'id' in d) return d as { id: string }
throw new Error('Invalid')
},
})

See also