🌐
GitHub
github.com › fastify › fastify-type-provider-typebox
GitHub - fastify/fastify-type-provider-typebox: A Type Provider for Typebox · GitHub
It provides a re-export of the TypeBox Type.* builder for convenience as well as providing additional utility types and optional validation infrastructure that can be useful when leveraging TypeBox with Fastify.
Starred by 203 users
Forked by 29 users
Languages   JavaScript 53.0% | TypeScript 47.0%
🌐
Fastify
fastify.dev › reference › type-providers
Fastify - Fast and Low Overhead Web Framework
In encapsulated usage, one can remap the context to use one or more providers (for example, typebox and json-schema-to-ts can be used in the same application). ... It is important to note that since the types do not propagate globally, it is currently not possible to avoid multiple registrations on routes when dealing with several scopes, as shown below: ... When working with modules, use FastifyInstance with Type Provider generics.
Discussions

Fastify: Support for Auto Type Inference (similar to TRPC)
I guess OP did not explain one of the Fastify core features. On their website Schema based: even if it is not mandatory we recommend to use JSON Schema to validate your routes and serialize your outputs, internally Fastify compiles the schema in a highly performant function. It uses JSON Schema to do the run-time validation. That's different from TypeScript compile-time type-safety. JSON schema provides some basic abilities to do the validations, which might be good enough for most cases. By default Fastify uses Ajv to do the validation, but as the OP mentioned in another comment, you can switch to something else. Also, if you need to provide an OpenAPI/Swagger schema/documentation, there are also some plugins that can directly generate it from the Fastify end-points + JSON Schemas. The pain-points Fastify trying to resolve are, with JSON-schema-first approach, you simply write the JSON schema once, then you will get: solid validation with JSON schema on the end-points. with minimum work, like type IFooRequestParams = Static, you will get TypeScript types, which can be used in both back-end and front-end just to add a plugin, you will get OpenAPI schema. Of course only for end-points, you still have to write some general info of OpenAPI schema. With traditional back-ends, you have to manually validate API end-point parameters, write your OpenAPI schema separately, declare your types manually which easily go out-of-sync from your OpenAPI documentation. You do something once - JSON schema, and you will basically get other benefits for free: validation, OpenAPI schema, TS types for back-end, TS types reusable in front-end. If you don't need the validation and/or OpenAPI doc, it requires more work and sounds stupid. Actually, the whole point is JSON schema. There are a lot of resources built based on JSON schema. So you can write less code and get more benefits from the open-source community. btw, after did some research in the last month, I've totally bought what Fastify is selling. I will push Schema-Driven Development in my team soon. More on reddit.com
🌐 r/typescript
25
13
February 16, 2023
How do you validate request and response in Fastify ? (Zod or JSON Schema)
Why not use TypeBox which is officially supported? More on reddit.com
🌐 r/node
19
7
January 4, 2025
Issues with Fastify + TypeBox
Thank you so much for this! I can see this indeed works, but this won't let me use type-checking with TypeScript, would it? I was simply referring to: https://fastify.dev/docs/latest/Reference/TypeScript/#typebox which shows the usage of generics: More on github.com
🌐 github.com
1
0
Fastify Typescript Boilerplate
tsconfig-paths, tsc-alias, ts-node, nodemon, source-map-support and swc can all be replaced by tsx, using nodemon on a new project these days seems a bit like using something familiar especially since if you were keeping to JavaScript, node now natively watches for changes . Be mindful with using cross-env in a shared project, most of the time the job it does can be done with a .env file and means less dependencies, especially when it's not necessary on Linux / Mac / Windows with WSL2 or Windows with git bash. In your eslint config, I personally dislike airbnb because it includes stylistic actions but it's widely used so that's subjective, You didn't put the prettier config last which defeats its purpose. Also continuing the trend of opinionated stuff, using eslint-plugin-prettier can be considered by some to be very bad practice which you can read more about here and here Anyway, onto the main course. The code. First off, this doesn't look like Fastify, it looks like Nest.js ported to Fastify. You have used the logical OR (||) in a lot of places that ideally should be the Nullish coalescing operator ?? . You can ditch envalid too, you have Typebox and since you're using Fastify, you can use @fastify/env as well, that also lets you drop dotenv from your dependencies too. Try this instead import { Type, type Static } from '@sinclair/typebox import Fastify from 'fastify' import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' const app = Fastify().withTypeProvider() const schema = Type.Object({ NODE_ENV: Type.String() }); await app.register(fastifyEnv, { dotenv: true, schema }) declare module 'fastify' { interface FastifyInstance { config: Static } } declare global { namespace NodeJS { interface ProcessEnv extends Static {} } } Another thing you've done is pull in all the plugins to Fastify into one app.ts file and then load them in order, that works but you can chunk up your application if you embrace the Fastify encapsulated modules concept. Think Nest.js modules but in Fastify fashion. Move all your "services" to a modules folder, then in your app instantiating file include something like this to load every Fastify plugin in your module folder import { resolve, dirname } from 'node:path' import { fileURLToPath } from 'node:url' import Fastify from 'fastify' import fastifyAutoload from '@fastify/autoload' import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' const app = Fastify().withTypeProvider() await app.register(fastifyAutoload, { dir: resolve(dirname(fileURLToPath(import.meta.url)), 'modules') }) As for what the module files would look like? Well, something like this. import fp from 'fastify-plugin' import type { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox' const prismaService: FastifyPluginAsyncTypebox = async (app) => { await app.decorate('prisma', new PrismaClient()) } export default fp(prismaService, { name: 'prismaService', /** This would be another module you make that just loads @fastify/env */ dependencies: 'env' }) declare module 'fastify' { interface FastifyInstance { prisma: PrismaClient } } I noticed in your initializeRoute.ts file, you had figured out the plugin pattern but had yet to find the built in types to make like easier. You want to use this instead: export const initializeRoutes: FastifyPluginCallbackTypebox<{ exampleOption: string }> = (server, options, done) => { ... } The HttpException class you created only exists to feel like nest.js in your service classes. You can ditch that and move your logic to the modules and with @fastify/sensible , you can quickly send errors using the decorated route handlers such as reply.notFound() Overall, it's a pretty neat project, I think you should check out this conference talk on how to structure a Fastify project if you're still excited for Fastify after my wall of text. edit: syntax corrections More on reddit.com
🌐 r/node
10
28
August 4, 2023
🌐
GitHub
github.com › foodsy-app › fastify-typebox
GitHub - foodsy-app/fastify-typebox: Plugin for Fastify to prevent having to write duplicate type definitions for schemas.
Plugin for Fastify to prevent having to write duplicate type definitions for schemas. - foodsy-app/fastify-typebox
Author   foodsy-app
🌐
GitHub
github.com › sinclairzx81 › fastify-typebox
GitHub - sinclairzx81/fastify-typebox: Enhanced TypeBox support for Fastify · GitHub
This library provides enhanced TypeBox support for Fastify. It enables automatic type inference for Fastify requests with no additional type hinting required. This library achieves this by remapping the Fastify interface using TypeScript conditional ...
Author   sinclairzx81
🌐
npm
npmjs.com › package › fastify-typebox
fastify-typebox - npm
November 22, 2021 - This library provides enhanced TypeBox support for Fastify. It enables automatic type inference for Fastify requests with no additional type hinting required. This library achieves this by remapping the Fastify interface using TypeScript conditional ...
      » npm install fastify-typebox
    
Published   Nov 22, 2021
Version   0.9.2
🌐
npm
npmjs.com › package › @foodsy-app › fastify-typebox
@foodsy-app/fastify-typebox - npm
@foodsy-app/fastify-typebox uses typebox, to compose JSON schemas.
      » npm install @foodsy-app/fastify-typebox
    
Published   Mar 28, 2021
Version   5.3.0
Author   foodsy-app
🌐
Reddit
reddit.com › r/typescript › fastify: support for auto type inference (similar to trpc)
r/typescript on Reddit: Fastify: Support for Auto Type Inference (similar to TRPC)
February 16, 2023 -

Documentation

https://www.fastify.io/docs/latest/Reference/Type-Providers/

Example

import Fastify, { FastifyTypeProvider } from 'fastify'
import { Type, Static, TSchema } from '@sinclair/typebox'

export interface TypeBoxTypeProvider extends FastifyTypeProvider {
  output: this['input'] extends TSchema ? Static<this['input']> : unknown
}

const fastify = Fastify()

fastify.withTypeProvider<TypeBoxTypeProvider>().post('/add', {
  schema: {
    body: Type.Object({
      a: Type.Number(),
      b: Type.Number()
    }),
    response: {
      200: Type.Number()
    }
  }
}, (req, reply) => {
  const { a, b } = req.body     // auto-type-checked
  reply.status(200).send(a + b) // auto-type-checked
})

Libraries

  • https://github.com/turkerdev/fastify-type-provider-zod

  • https://github.com/fastify/fastify-type-provider-typebox

  • https://github.com/fastify/fastify-type-provider-json-schema-to-ts

Top answer
1 of 4
7
I guess OP did not explain one of the Fastify core features. On their website Schema based: even if it is not mandatory we recommend to use JSON Schema to validate your routes and serialize your outputs, internally Fastify compiles the schema in a highly performant function. It uses JSON Schema to do the run-time validation. That's different from TypeScript compile-time type-safety. JSON schema provides some basic abilities to do the validations, which might be good enough for most cases. By default Fastify uses Ajv to do the validation, but as the OP mentioned in another comment, you can switch to something else. Also, if you need to provide an OpenAPI/Swagger schema/documentation, there are also some plugins that can directly generate it from the Fastify end-points + JSON Schemas. The pain-points Fastify trying to resolve are, with JSON-schema-first approach, you simply write the JSON schema once, then you will get: solid validation with JSON schema on the end-points. with minimum work, like type IFooRequestParams = Static, you will get TypeScript types, which can be used in both back-end and front-end just to add a plugin, you will get OpenAPI schema. Of course only for end-points, you still have to write some general info of OpenAPI schema. With traditional back-ends, you have to manually validate API end-point parameters, write your OpenAPI schema separately, declare your types manually which easily go out-of-sync from your OpenAPI documentation. You do something once - JSON schema, and you will basically get other benefits for free: validation, OpenAPI schema, TS types for back-end, TS types reusable in front-end. If you don't need the validation and/or OpenAPI doc, it requires more work and sounds stupid. Actually, the whole point is JSON schema. There are a lot of resources built based on JSON schema. So you can write less code and get more benefits from the open-source community. btw, after did some research in the last month, I've totally bought what Fastify is selling. I will push Schema-Driven Development in my team soon.
2 of 4
2
Nice addition but it is as verbose as it can get. That's generally what I don like about fastify in general, that TS looks like an afterthought, which especially for a server that sends/receive data with shapes isn't good.
🌐
Medium
medium.com › @damien_16960 › fastify-x-date-x-sinclair-typebox-19b24a370c6c
Fastify x Date x @sinclair/typebox | by Damien | Medium
June 3, 2024 - In my project, I use the Fastify framework for my API and @sinclair/typebox for validating incoming and outgoing data.
🌐
GitHub
github.com › dwickern › fastify-typebox
GitHub - dwickern/fastify-typebox: Plugin for Fastify to prevent having to write duplicate type definitions for schemas. · GitHub
Plugin for Fastify to prevent having to write duplicate type definitions for schemas. - dwickern/fastify-typebox
Author   dwickern
Find elsewhere
🌐
Medium
gkhanko.medium.com › how-to-setup-a-nodejs-api-with-fastify-typescript-runtime-type-support-35606c0b657b
How to Setup a NodeJS API with Fastify (TypeScript + runtime type support) | by Gökhan Koç | Medium
November 18, 2024 - In this article, I’ll show you how to set up a NodeJS API using Fastify that automatically generates Swagger documentation from your TypeScript types. ... Check out the GitHub repository for the complete template. ... This leads to three separate definitions that need to be kept in sync. With TypeBox, you define your types once, and you get all three:
🌐
Reddit
reddit.com › r/node › how do you validate request and response in fastify ? (zod or json schema)
r/node on Reddit: How do you validate request and response in Fastify ? (Zod or JSON Schema)
January 4, 2025 - This should work automatically if you define the schema with TypeBox correctly. You need to use the correct type provider though. https://github.com/fastify/fastify-type-provider-typebox
🌐
npm
npmjs.com › package › @fastify › type-provider-typebox › v › 2.0.1
fastify/type-provider-typebox
June 30, 2022 - import Fastify from 'fastify' import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' import { Type } from '@sinclair/typebox' const fastify = Fastify().withTypeProvider<TypeBoxTypeProvider>() fastify.get('/', { 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 })
      » npm install @fastify/type-provider-typebox
    
Published   Oct 19, 2025
Version   2.0.1
🌐
CodeSandbox
codesandbox.io › examples › package › @fastify › type-provider-typebox
fastify/type-provider-typebox examples
Use this online @fastify/type-provider-typebox playground to view and fork @fastify/type-provider-typebox example apps and templates on CodeSandbox.
🌐
GitHub
github.com › fastify › fastify-type-provider-typebox › releases
Releases · fastify/fastify-type-provider-typebox
A Type Provider for Typebox. Contribute to fastify/fastify-type-provider-typebox development by creating an account on GitHub.
Author   fastify
🌐
CodeSandbox
codesandbox.io › examples › package › fastify-typebox
fastify-typebox examples - CodeSandbox
Use this online fastify-typebox playground to view and fork fastify-typebox example apps and templates on CodeSandbox.
🌐
GitHub
github.com › fastify › fastify › discussions › 5302
Issues with Fastify + TypeBox · fastify/fastify · Discussion #5302
// types.ts export type FastifyTypebox = FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, FastifyBaseLogger, TypeBoxTypeProvider> export const RouteSignupReqBody = Type.Object({ email: Type.String({ format: 'email' }), name: Type.String() }) export const RouteSignupRes = Type.Object({ email: Type.String({ format: 'email' }), id: Type.String(), name: Type.String() }) export type TRouteSignupRes = Static<typeof RouteSignupRes> export type TRouteSignupReqBody = Static<typeof RouteSignupReqBody>
Author   fastify
🌐
GitHub
github.com › xStrixU › fastify-typebox-utils
GitHub - xStrixU/fastify-typebox-utils: Utility types and functions for easier Fastify integration with TypeBox
The advantage of this approach is that this is fully typed with FastifySchema. // schemas.ts import { Type } from '@sinclair/typebox'; import { createTypeBoxFastifySchema } from '@xstrixu/fastify-typebox-utils'; export const fooSchema = createTypeBoxFastifySchema({ body: Type.Object({ foo: Type.String(), bar: Type.Number(), baz: Type.Boolean(), }), response: { 200: Type.Object({ message: Type.String(), }), 400: Type.Number(), }, });
Author   xStrixU
🌐
Nodeland
adventures.nodeland.dev › archive › type-safe-fastify-javascript-sandboxing-and-other
Type-Safe Fastify, JavaScript sandboxing and other Adventures in Nodeland
July 31, 2023 - In my latest youtube tutorial, Type-Safe Fastify I show how to integrate @sinclair/typebox with Fastify using @fastify/type-provider-typebox!
🌐
Platformatic
blog.platformatic.dev › fastify-fundamentals-how-to-validate-api-responses
Fastify Fundamentals: How to Validate API Responses
February 23, 2024 - In this tutorial, we’ve explored how to use the AJV Schema validator in your Fastify applications and how to handle subsequent errors. In addition, you should now be able to specify a custom schema that your API returns by implementing serialization. Lastly, we delved into how to build type-safe validations with tools such as Typebox.
🌐
Reddit
reddit.com › r/node › fastify typescript boilerplate
r/node on Reddit: Fastify Typescript Boilerplate
August 4, 2023 -

Hi,
I have developed a boilerplate for my Fastify projects.

Link: https://github.com/TheB1gFatPanda/fastify-typescript-starter

The boilerplate contains :

  • Fastify + typescript

  • Prisma ORM

  • Eslint + Prettier

  • Swagger Documentation

  • SWC

I would really appreciate your feedback and how I can improve the codebase

Top answer
1 of 5
16
tsconfig-paths, tsc-alias, ts-node, nodemon, source-map-support and swc can all be replaced by tsx, using nodemon on a new project these days seems a bit like using something familiar especially since if you were keeping to JavaScript, node now natively watches for changes . Be mindful with using cross-env in a shared project, most of the time the job it does can be done with a .env file and means less dependencies, especially when it's not necessary on Linux / Mac / Windows with WSL2 or Windows with git bash. In your eslint config, I personally dislike airbnb because it includes stylistic actions but it's widely used so that's subjective, You didn't put the prettier config last which defeats its purpose. Also continuing the trend of opinionated stuff, using eslint-plugin-prettier can be considered by some to be very bad practice which you can read more about here and here Anyway, onto the main course. The code. First off, this doesn't look like Fastify, it looks like Nest.js ported to Fastify. You have used the logical OR (||) in a lot of places that ideally should be the Nullish coalescing operator ?? . You can ditch envalid too, you have Typebox and since you're using Fastify, you can use @fastify/env as well, that also lets you drop dotenv from your dependencies too. Try this instead import { Type, type Static } from '@sinclair/typebox import Fastify from 'fastify' import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' const app = Fastify().withTypeProvider() const schema = Type.Object({ NODE_ENV: Type.String() }); await app.register(fastifyEnv, { dotenv: true, schema }) declare module 'fastify' { interface FastifyInstance { config: Static } } declare global { namespace NodeJS { interface ProcessEnv extends Static {} } } Another thing you've done is pull in all the plugins to Fastify into one app.ts file and then load them in order, that works but you can chunk up your application if you embrace the Fastify encapsulated modules concept. Think Nest.js modules but in Fastify fashion. Move all your "services" to a modules folder, then in your app instantiating file include something like this to load every Fastify plugin in your module folder import { resolve, dirname } from 'node:path' import { fileURLToPath } from 'node:url' import Fastify from 'fastify' import fastifyAutoload from '@fastify/autoload' import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' const app = Fastify().withTypeProvider() await app.register(fastifyAutoload, { dir: resolve(dirname(fileURLToPath(import.meta.url)), 'modules') }) As for what the module files would look like? Well, something like this. import fp from 'fastify-plugin' import type { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox' const prismaService: FastifyPluginAsyncTypebox = async (app) => { await app.decorate('prisma', new PrismaClient()) } export default fp(prismaService, { name: 'prismaService', /** This would be another module you make that just loads @fastify/env */ dependencies: 'env' }) declare module 'fastify' { interface FastifyInstance { prisma: PrismaClient } } I noticed in your initializeRoute.ts file, you had figured out the plugin pattern but had yet to find the built in types to make like easier. You want to use this instead: export const initializeRoutes: FastifyPluginCallbackTypebox<{ exampleOption: string }> = (server, options, done) => { ... } The HttpException class you created only exists to feel like nest.js in your service classes. You can ditch that and move your logic to the modules and with @fastify/sensible , you can quickly send errors using the decorated route handlers such as reply.notFound() Overall, it's a pretty neat project, I think you should check out this conference talk on how to structure a Fastify project if you're still excited for Fastify after my wall of text. edit: syntax corrections
2 of 5
5
This looks pretty decent but is too opinionated. The flat structure is a no-go for most node devs (see component structure ). This is not good: req.body as LoginUser; typebox is capable of inferring types from schemas, but it cannot do it because of how things are structured here. I use "routes" for routing, and "controllers" for processing requests including the validation, so the types are validated in inferred right in the controller. Official Fastify examples show how to keep both route and controller in one, and this is also type-safe. customResponse(reply, { statusCode: 201, data, error: false, message: 'login' }); I love how Fastify allows to simply return the data, and you can specify a return type on the request handler. "customResponse" kill this feature, and what it does should be done instead by a plugin. Global error handling should be configured, so instead of this: const findUser = await this.db.user.findUnique({ where: { email: getUserData.email } }); if (!findUser) { throw new HttpException(404, 'User not found'); } You can use "findUniqueOrThrow", and handle the known Prisma error centrally in a global handler. "Service" layer shouldn't know about HTTP. Instead, define your own error classes like "NotFound", throw them from any place, and catch them in a global error handler. Would be nice for the boilerplate to have a few tests. Fastify has much better utils for testing than Express, it's quite easy to make fake requests and assert data.