Skip to main content
The Feathers schema system provides a powerful, type-safe approach to data validation and transformation. It uses JSON Schema for validation and offers seamless integration with TypeBox for TypeScript type inference.

Key Concepts

The schema system consists of three main components:
1

Schema Definition

Define your data structure using JSON Schema or TypeBox. Schemas provide type safety and validation.
2

Validation

Automatically validate incoming data against your schema using AJV validators.
3

Resolvers

Transform and resolve data properties, including virtual properties and secure data handling.

Installation

Install the required packages:
npm install @feathersjs/schema @feathersjs/typebox

Basic Schema Definition

Using JSON Schema

Define schemas using standard JSON Schema format:
import { schema, FromSchema } from '@feathersjs/schema'

const userSchema = schema({
  $id: 'User',
  type: 'object',
  additionalProperties: false,
  required: ['email'],
  properties: {
    email: { type: 'string' },
    password: { type: 'string' }
  }
} as const)

// Infer TypeScript type from schema
type User = FromSchema<typeof userSchema>

Using TypeBox

TypeBox provides a more TypeScript-friendly API:
import { Type } from '@feathersjs/typebox'
import { getValidator } from '@feathersjs/typebox'
import { Ajv } from '@feathersjs/schema'

const userSchema = Type.Object({
  email: Type.String(),
  password: Type.String(),
  age: Type.Optional(Type.Number())
})

const validator = getValidator(userSchema, new Ajv())

Schema Validation

Schemas can automatically validate and coerce data:
const messageSchema = schema({
  $id: 'message',
  type: 'object',
  required: ['text', 'read'],
  additionalProperties: false,
  properties: {
    text: { type: 'string' },
    read: { type: 'boolean' },
    upvotes: { type: 'number' }
  }
} as const)

// Validates and coerces types
const message = await messageSchema.validate({
  text: 'hello',
  read: 0,        // Coerced to false
  upvotes: '10'   // Coerced to 10
})
// Result: { text: 'hello', read: false, upvotes: 10 }

Query Syntax

Create schemas for Feathers query syntax with operators like $gt, $lt, $in:
import { querySyntax } from '@feathersjs/typebox'
import { Type, Static } from '@feathersjs/typebox'

const messageSchema = Type.Object({
  text: Type.String(),
  userId: Type.Number()
})

const messageQuerySchema = querySyntax(messageSchema)

type MessageQuery = Static<typeof messageQuerySchema>

// Valid queries
const query: MessageQuery = {
  userId: { $gt: 10, $in: [20, 30] },
  text: 'hello',
  $select: ['text', 'userId'],
  $sort: { userId: 1 },
  $limit: 10,
  $skip: 0
}

Type Inference

The schema system provides full TypeScript type inference:
import { Infer, schema } from '@feathersjs/schema'
import { Type, Static } from '@feathersjs/typebox'

// With JSON Schema
const jsonSchema = schema({
  $id: 'Example',
  type: 'object',
  properties: {
    name: { type: 'string' }
  }
} as const)

type JsonType = Infer<typeof jsonSchema>

// With TypeBox
const typeboxSchema = Type.Object({
  name: Type.String()
})

type TypeBoxType = Static<typeof typeboxSchema>

Schema Extension

Extend existing schemas to create new ones:
const userDataSchema = schema({
  $id: 'UserData',
  type: 'object',
  required: ['email'],
  properties: {
    email: { type: 'string' },
    password: { type: 'string' }
  }
} as const)

// Extend with additional properties
const userSchema = schema({
  $id: 'User',
  type: 'object',
  required: ['id', ...userDataSchema.definition.required],
  properties: {
    ...userDataSchema.definition.properties,
    id: { type: 'number' },
    createdAt: { type: 'string' }
  }
} as const)

Next Steps

Data Validation

Learn how to validate data in hooks and services

Schema Resolvers

Transform data with resolvers and virtual properties