Install @fastify/type-provider-typebox
mainInstall @fastify/type-provider-typebox along with typebox (which is a required peer dependency) using npm:
npm i typebox
npm i @fastify/type-provider-typeboxrepository·main·Indexed 41 days ago
https://github.com/fastify/fastify-type-provider-typeboxA Type Provider for TypeBox over Fastify (version 6.1.0) that enables seamless type inference for request bodies, queries, and responses in TypeScript and JavaScript projects. It integrates TypeBox with Fastify's Type Provider infrastructure and includes the TypeBoxValidatorCompiler for high-performance runtime type checking and automatic value conversion.
Install @fastify/type-provider-typebox along with typebox (which is a required peer dependency) using npm:
npm i typebox
npm i @fastify/type-provider-typeboxTo enable type inference for your routes, you must call .withTypeProvider<TypeBoxTypeProvider>() immediately after initializing Fastify.
Important: You cannot call .withTypeProvider() on an existing Fastify instance; it must be chained during initialization.
import Fastify from 'fastify'
import { Type, TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
const fastify = Fastify().withTypeProvider<TypeBoxTypeProvider>()When using the TypeBoxValidatorCompiler, standard string formats like date or date-time are not registered by default. You must register them explicitly using registerAjvFormats (or similar utility) to ensure they are validated correctly.
import { registerAjvFormats } from '@fastify/type-provider-typebox'
registerAjvFormats()For plain JavaScript projects using checkJs, you can apply the type provider using JSDoc type casts.
For a Fastify Instance:
/** @typedef {import('fastify').FastifyInstance<import('fastify').RawServerDefault, import('fastify').RawRequestDefaultExpression, import('fastify').RawReplyDefaultExpression, import('fastify').FastifyBaseLogger, import('@fastify/type-provider-typebox').TypeBoxTypeProvider>} FastifyTypeBox */
const fastify = /** @type {FastifyTypeBox} */ (Fastify())For Plugins:
/** @type {import('@fastify/type-provider-typebox').FastifyPluginAsyncTypebox} */
const plugin = async (fastify) => {
// routes registered here get full type inference
}import Fastify from 'fastify'
import { Type } from '@fastify/type-provider-typebox'
/** @typedef {import('fastify').FastifyInstance<import('fastify').RawServerDefault, import('fastify').RawRequestDefaultExpression, import('fastify').RawReplyDefaultExpression, import('fastify').FastifyBaseLogger, import('@fastify/type-provider-typebox').TypeBoxTypeProvider>} FastifyTypeBox */
const fastify = /** @type {FastifyTypeBox} */ (Fastify())
fastify.post('/', {
schema: {
body: Type.Object({ x: Type.String() })
}
}, (req) => {
const { x } = req.body // inferred as string
})This example demonstrates how to define a route schema using the re-exported Type builder and how the request body types are automatically inferred in the handler.
import Fastify from 'fastify'
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
// This package re-export Typebox package
// but you can also use any builders imported
// directly from typebox
import { Type } from 'typebox'
const fastify = Fastify().withTypeProvider<TypeBoxTypeProvider>()
fastify.post('/', {
schema: {
body: Type.Object({
x: Type.String(),
y: Type.Number(),
z: Type.Boolean()
})
}
}, (req) => {
// The `x`, `y`, `z` types are automatically inferred
const { x, y, z } = req.body
})When defining a plugin using FastifyPluginAsyncTypebox, you do not need to call .withTypeProvider() inside the plugin to get full type inference for routes registered within it.
import { Type, FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox'
const plugin: FastifyPluginAsyncTypebox = async function(fastify, _opts) {
fastify.get('/', {
schema: {
body: Type.Object({
x: Type.String(),
y: Type.Number(),
z: Type.Boolean()
})
}
}, (req) => {
/// The `x`, `y`, and `z` types are automatically inferred
const { x, y, z } = req.body
});
}To perform high-performance runtime type checking, you can enable the TypeBox compiler by passing TypeBoxValidatorCompiler to .setValidatorCompiler(). This compiler is limited to types expressible through the TypeBox Type.* namespace.
import { Type, TypeBoxTypeProvider, TypeBoxValidatorCompiler } from '@fastify/type-provider-typebox'
import Fastify from 'fastify'
const fastify = Fastify().setValidatorCompiler(TypeBoxValidatorCompiler)
fastify.withTypeProvider<TypeBoxTypeProvider>().get('/', {
schema: {
querystring: Type.Object({
x: Type.String(),
y: Type.String(),
z: Type.String()
})
}
}, (req) => {
const { x, y, z } = req.query
})When you need to manually type your route handlers (e.g., when extracting them from the main file), use FastifyRequestTypeBox and FastifyReplyTypeBox. These types accept a schema as a generic to provide full inference for req.body, req.query, etc.
import type { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
import { Type } from '@fastify/type-provider-typebox';
import type {
ContextConfigDefault,
FastifyBaseLogger,
FastifyInstance,
FastifyReply,
FastifyRequest,
RawReplyDefaultExpression,
RawRequestDefaultExpression,
RawServerDefault,
} from 'fastify';
import type { RouteGenericInterface } from 'fastify/types/route';
import type { FastifySchema } from 'fastify/types/schema';
export type FastifyTypeBox = FastifyInstance<
RawServerDefault,
RawRequestDefaultExpression,
RawReplyDefaultExpression,
FastifyBaseLogger,
TypeBoxTypeProvider
>;
export type FastifyRequestTypeBox<TSchema extends FastifySchema> = FastifyRequest<
RouteGenericInterface,
RawServerDefault,
RawRequestDefaultExpression,
TSchema,
TypeBoxTypeProvider
>;
export type FastifyReplyTypeBox<TSchema extends FastifySchema> = FastifyReply<
RouteGenericInterface,
RawServerDefault,
RawRequestDefaultExpression,
RawReplyDefaultExpression,
ContextConfigDefault,
TSchema,
TypeBoxTypeProvider
>;
export const CreateProductSchema = {
body: Type.Object({
name: Type.String(),
price: Type.Number(),
}),
response: {
201: Type.Object({
id: Type.Number(),
}),
},
};
export const CreateProductHandler = (
req: FastifyRequestTypeBox<typeof CreateProductSchema>,
reply: FastifyReplyTypeBox<typeof CreateProductSchema>,
) => {
// The `name` and `price` types are automatically inferred
const { name, price } = req.body;
// The response body type is automatically inferred
reply.status(201).send({ id: 'string-value' });
// ^? error TS2322: Type 'string' is not assignable to type 'number'.
};Use the Format module to register custom string validation formats.
import { Format } from '@fastify/type-provider-typebox'
Format.Set('custom-format', (value) => value === 'custom');
Format.Set('regex-format', (value) => /^my-format$/.test(value));Ensure your Fastify version is compatible with the installed plugin version:
| Plugin version | Fastify version |
|---|---|
>=5.x | ^5.x |
>=1.x <5.x | ^4.x |
Note that if a Fastify version is out of support, the corresponding plugin versions are also out of support.
| Plugin version | Fastify version |
| ---------------|-----------------|
| `>=5.x` | `^5.x` |
| `>=1.x <5.x` | `^4.x` |To enable automatic type inference for your routes (allowing TypeScript to know the shape of request.body, request.query, etc., based on your TypeBox schemas), use the TypeBoxTypeProvider interface with the .withTypeProvider<T>() method on your Fastify instance.
import Fastify from 'fastify'
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
const server = Fastify().withTypeProvider<TypeBoxTypeProvider>()When writing Fastify plugins that should benefit from TypeBox type inference, use the specialized plugin types provided by the package. This ensures the fastify instance passed to your plugin is correctly typed with TypeBoxTypeProvider.
Available types:
FastifyPluginAsyncTypebox: For async plugins.FastifyPluginCallbackTypebox: For callback-based plugins.import { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox'
const plugin: FastifyPluginAsyncTypebox = async (fastify, options) => {
// fastify is typed with TypeBoxTypeProvider here
}