TypeScript
TypeScript
The Fastify framework is written in vanilla JavaScript, and as such type definitions are not as easy to maintain; however, since version 2 and beyond, maintainers and contributors have put in a great effort to improve the types.
The type system was changed in Fastify version 3. The new type system introduces
generic constraining and defaulting, plus a new way to define schema types such
as a request body, querystring, and more! As the team works on improving
framework and type definition synergy, sometimes parts of the API will not be
typed or may be typed incorrectly. We encourage you to contribute to help us
fill in the gaps. Just make sure to read our
CONTRIBUTING.md
file before getting started to make sure things go smoothly!
The documentation in this section covers Fastify version 3.x typings
Plugins may or may not include typings. See Plugins for more information. We encourage users to send pull requests to improve typings support.
🚨 Don't forget to install @types/node
Learn By Example
The best way to learn the Fastify type system is by example! The following four examples should cover the most common Fastify development cases. After the examples there is further, more detailed documentation for the type system.
Getting Started
This example will get you up and running with Fastify and TypeScript. It results in a blank http Fastify server.
- Create a new npm project, install Fastify, and install typescript & Node.js types as peer dependencies:
npm init -y
npm i fastify
npm i -D typescript @types/node
- Add the following lines to the
"scripts"section of thepackage.json:
{
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "node index.js"
}
}
- Initialize a TypeScript configuration file:
npx tsc --init
or use one of the recommended ones.
Note: Set target property in tsconfig.json to es2017 or greater to avoid
FastifyDeprecation warning.
- Create an
index.tsfile - this will contain the server code - Add the following code block to your file:
import fastify from 'fastify'
const server = fastify()
server.get('/ping', async (request, reply) => {
return 'pong\n'
})
server.listen({ port: 8080 }, (err, address) => {
if (err) {
console.error(err)
process.exit(1)
}
console.log(`Server listening at ${address}`)
}) - Run
npm run build- this will compileindex.tsintoindex.jswhich can be executed using Node.js. If you run into any errors please open an issue in fastify/help - Run
npm run startto run the Fastify server - You should see
Server listening at http://127.0.0.1:8080in your console - Try out your server using
curl localhost:8080/ping, it should returnpong🏓
🎉 You now have a working Typescript Fastify server! This example demonstrates
the simplicity of the version 3.x type system. By default, the type system
assumes you are using an http server. The later examples will demonstrate how
to create more complex servers such as https and http2, how to specify route
schemas, and more!
For more examples on initializing Fastify with TypeScript (such as enabling HTTP2) check out the detailed API section here
Using Generics
The type system heavily relies on generic properties to provide the most
accurate development experience. While some may find the overhead a bit
cumbersome, the tradeoff is worth it! This example will dive into implementing
generic types for route schemas and the dynamic properties located on the
route-level request object.
-
If you did not complete the previous example, follow steps 1-4 to get set up.
-
Inside
index.ts, define three interfacesIQuerystring,IHeadersandIReply:interface IQuerystring {
username: string;
password: string;
}
interface IHeaders {
'h-Custom': string;
}
interface IReply {
200: { success: boolean };
302: { url: string };
'4xx': { error: string };
} -
Using the three interfaces, define a new API route and pass them as generics. The shorthand route methods (i.e.
.get) accept a generic objectRouteGenericInterfacecontaining five named properties:Body,Querystring,Params,HeadersandReply. The interfacesBody,Querystring,ParamsandHeaderswill be passed down through the route method into the route method handlerrequestinstance and theReplyinterface to thereplyinstance.server.get<{
Querystring: IQuerystring,
Headers: IHeaders,
Reply: IReply
}>('/auth', async (request, reply) => {
const { username, password } = request.query
const customerHeader = request.headers['h-Custom']
// do something with request data
// chaining .statusCode/.code calls with .send allows type narrowing. For example:
// this works
reply.code(200).send({ success: true });
// but this gives a type error
reply.code(200).send('uh-oh');
// it even works for wildcards
reply.code(404).send({ error: 'Not found' });
return { success: true }
}) -
Build and run the server code with
npm run buildandnpm run start -
Query the API
curl localhost:8080/auth?username=admin&password=Password123!And it should return back
logged in! -
But wait there's more! The generic interfaces are also available inside route level hook methods. Modify the previous route by adding a
preValidationhook:server.get<{
Querystring: IQuerystring,
Headers: IHeaders,
Reply: IReply
}>('/auth', {
preValidation: (request, reply, done) => {
const { username, password } = request.query
done(username !== 'admin' ? new Error('Must be admin') : undefined) // only validate `admin` account
}
}, async (request, reply) => {
const customerHeader = request.headers['h-Custom']
// do something with request data
return { success: true }
}) -
Build and run and query with the
usernamequery string option set to anything other thanadmin. The API should now return a HTTP 500 error{"statusCode":500,"error":"Internal Server Error","message":"Must be admin"}
🎉 Good work, now you can define interfaces for each route and have strictly typed request and reply instances. Other parts of the Fastify type system rely on generic properties. Make sure to reference the detailed type system documentation below to learn more about what is available.
JSON Schema
To validate your requests and responses you can use JSON Schema files. If you didn't know already, defining schemas for your Fastify routes can increase their throughput! Check out the Validation and Serialization documentation for more info.
Also it has the advantage to use the defined type within your handlers (including pre-validation, etc.).
Here are some options on how to achieve this.
Fastify Type Providers
Fastify offers two packages wrapping json-schema-to-ts and typebox:
And a zod wrapper by a third party called fastify-type-provider-zod
They simplify schema validation setup and you can read more about them in Type Providers page.
Below is how to setup schema validation using the typebox,
json-schema-to-typescript, and json-schema-to-ts packages without type
providers.
TypeBox
A useful library for building types and a schema at once is TypeBox. With TypeBox you define your schema within your code and use them directly as types or schemas as you need them.
When you want to use it for validation of some payload in a fastify route you can do it as follows:
-
Install
typeboxin your project.npm i @sinclair/typebox -
Define the schema you need with
Typeand create the respective type withStatic.import { Static, Type } from '@sinclair/typebox'
export const User = Type.Object({
name: Type.String(),
mail: Type.Optional(Type.String({ format: 'email' })),
})
export type UserType = Static<typeof User> -
Use the defined type and schema during the definition of your route
import Fastify from 'fastify'
// ...
const fastify = Fastify()
fastify.post<{ Body: UserType, Reply: UserType }>(
'/',
{
schema: {
body: User,
response: {
200: User
},
},
},
(request, reply) => {
// The `name` and `mail` types are automatically inferred
const { name, mail } = request.body;
reply.status(200).send({ name, mail });
}
)
json-schema-to-typescript
In the last example we used Typebox to define the types and schemas for our route. Many users will already be using JSON Schemas to define these properties, and luckily there is a way to transform existing JSON Schemas into TypeScript interfaces!
-
If you did not complete the 'Getting Started' example, go back and follow steps 1-4 first.
-
Install the
json-schema-to-typescriptmodule:npm i -D json-schema-to-typescript -
Create a new folder called
schemasand add two filesheaders.jsonandquerystring.json. Copy and paste the following schema definitions into the respective files:{
"title": "Headers Schema",
"type": "object",
"properties": {
"h-Custom": { "type": "string" }
},
"additionalProperties": false,
"required": ["h-Custom"]
}{
"title": "Querystring Schema",
"type": "object",
"properties": {
"username": { "type": "string" },
"password": { "type": "string" }
},
"additionalProperties": false,
"required": ["username", "password"]
} -
Add a
compile-schemasscript to the package.json:
{
"scripts": {
"compile-schemas": "json2ts -i schemas -o types"
}
}
json2ts is a CLI utility included in json-schema-to-typescript. schemas
is the input path, and types is the output path.
5. Run npm run compile-schemas. Two new files should have been created in the
types directory.
6. Update index.ts to have the following code:
import fastify from 'fastify'
// import json schemas as normal
import QuerystringSchema from './schemas/querystring.json'
import HeadersSchema from './schemas/headers.json'
// import the generated interfaces
import { QuerystringSchema as QuerystringSchemaInterface } from './types/querystring'
import { HeadersSchema as HeadersSchemaInterface } from './types/headers'
const server = fastify()
server.get<{
Querystring: QuerystringSchemaInterface,
Headers: HeadersSchemaInterface
}>('/auth', {
schema: {
querystring: QuerystringSchema,
headers: HeadersSchema
},
preValidation: (request, reply, done) => {
const { username, password } = request.query
done(username !== 'admin' ? new Error('Must be admin') : undefined)
}
// or if using async
// preValidation: async (request, reply) => {
// const { username, password } = request.query
// if (username !== "admin") throw new Error("Must be admin");
// }
}, async (request, reply) => {
const customerHeader = request.headers['h-Custom']
// do something with request data
return `logged in!`
})
server.route<{
Querystring: QuerystringSchemaInterface,
Headers: HeadersSchemaInterface
}>({
method: 'GET',
url: '/auth2',
schema: {
querystring: QuerystringSchema,
headers: HeadersSchema
},
preHandler: (request, reply, done) => {
const { username, password } = request.query
const customerHeader = request.headers['h-Custom']
done()
},
handler: (request, reply) => {
const { username, password } = request.query
const customerHeader = request.headers['h-Custom']
reply.status(200).send({username});
}
})
server.listen({ port: 8080 }, (err, address) => {
if (err) {
console.error(err)
process.exit(0)
}
console.log(`Server listening at ${address}`)
})
Pay special attention to the imports at the top of this file. It might seem redundant, but you need to import both the schema files and the generated interfaces.
Great work! Now you can make use of both JSON Schemas and TypeScript definitions.
json-schema-to-ts
If you do not want to generate types from your schemas, but want to use them directly from your code, you can use the package json-schema-to-ts.
You can install it as dev-dependency.
npm i -D json-schema-to-ts
In your code you can define your schema like a normal object. But be aware of making it const like explained in the docs of the module.
const todo = {
type: 'object',
properties: {
name: { type: 'string' },
description: { type: 'string' },
done: { type: 'boolean' },
},
required: ['name'],
} as const; // don't forget to use const !
With the provided type FromSchema you can build a type from your schema and
use it in your handler.
import { FromSchema } from "json-schema-to-ts";
fastify.post<{ Body: FromSchema<typeof todo> }>(
'/todo',
{
schema: {
body: todo,
response: {
201: {
type: 'string',
},
},
}
},
async (request, reply): Promise<void> => {
/*
request.body has type
{
[x: string]: unknown;
description?: string;
done?: boolean;
name: string;
}
*/
request.body.name // will not throw type error
request.body.notthere // will throw type error
reply.status(201).send();
},
);
Plugins
One of Fastify's most distinguishable features is its extensive plugin ecosystem. Plugin types are fully supported, and take advantage of the declaration merging pattern. This example is broken up into three parts: Creating a TypeScript Fastify Plugin, Creating Type Definitions for a Fastify Plugin, and Using a Fastify Plugin in a TypeScript Project.
Creating a TypeScript Fastify Plugin
- Initialize a new npm project and install required dependencies
npm init -y
npm i fastify fastify-plugin
npm i -D typescript @types/node - Add a
buildscript to the"scripts"section and'index.d.ts'to the"types"section of thepackage.jsonfile:{
"types": "index.d.ts",
"scripts": {
"build": "tsc -p tsconfig.json"
}
} - Initialize a TypeScript configuration file:
Once the file is generated, enable the
npx typescript --init"declaration"option in the"compilerOptions"object.{
"compilerOptions": {
"declaration": true
}
} - Create an
index.tsfile - this will contain the plugin code - Add the following code to
index.tsimport { FastifyPluginCallback, FastifyPluginAsync } from 'fastify'
import fp from 'fastify-plugin'
// using declaration merging, add your plugin props to the appropriate fastify interfaces
// if prop type is defined here, the value will be typechecked when you call decorate{,Request,Reply}
declare module 'fastify' {
interface FastifyRequest {
myPluginProp: string
}
interface FastifyReply {
myPluginProp: number
}
}
// define options
export interface MyPluginOptions {
myPluginOption: string
}
// define plugin using callbacks
const myPluginCallback: FastifyPluginCallback<MyPluginOptions> = (fastify, options, done) => {
fastify.decorateRequest('myPluginProp', 'super_secret_value')
fastify.decorateReply('myPluginProp', options.myPluginOption)
done()
}
// define plugin using promises
const myPluginAsync: FastifyPluginAsync<MyPluginOptions> = async (fastify, options) => {
fastify.decorateRequest('myPluginProp', 'super_secret_value')
fastify.decorateReply('myPluginProp', options.myPluginOption)
}
// export plugin using fastify-plugin
export default fp(myPluginCallback, '3.x')
// or
// export default fp(myPluginAsync, '3.x') - Run
npm run buildto compile the plugin code and produce both a JavaScript source file and a type definition file. - With the plugin now complete you can [publish to npm] or use it locally.
You do not need to publish your plugin to npm to use it. You can include it in a Fastify project and reference it as you would any piece of code! As a TypeScript user, make sure the declaration override exists somewhere that will be included in your project compilation so the TypeScript interpreter can process it.
Creating Type Definitions for a Fastify Plugin
This plugin guide is for Fastify plugins written in JavaScript. The steps outlined in this example are for adding TypeScript support for users consuming your plugin.
- Initialize a new npm project and install required dependencies
npm init -y
npm i fastify-plugin - Create two files
index.jsandindex.d.ts - Modify the package json to include these files under the
mainandtypesproperties (the name does not have to beindexexplicitly, but it is recommended the files have the same name):{
"main": "index.js",
"types": "index.d.ts"
} - Open
index.jsand add the following code:// fastify-plugin is highly recommended for any plugin you write
const fp = require('fastify-plugin')
function myPlugin (instance, options, done) {
// decorate the fastify instance with a custom function called myPluginFunc
instance.decorate('myPluginFunc', (input) => {
return input.toUpperCase()
})
done()
}
module.exports = fp(myPlugin, {
fastify: '5.x',
name: 'my-plugin' // this is used by fastify-plugin to derive the property name
}) - Open
index.d.tsand add the following code:import { FastifyPluginCallback } from 'fastify'
interface PluginOptions {
//...
}
// Optionally, you can add any additional exports.
// Here we are exporting the decorator we added.
export interface myPluginFunc {
(input: string): string
}
// Most importantly, use declaration merging to add the custom property to the Fastify type system
declare module 'fastify' {
interface FastifyInstance {
myPluginFunc: myPluginFunc
}
}
// fastify-plugin automatically adds named export, so be sure to add also this type
// the variable name is derived from `options.name` property if `module.exports.myPlugin` is missing
export const myPlugin: FastifyPluginCallback<PluginOptions>
// fastify-plugin automatically adds `.default` property to the exported plugin. See the note below
export default myPlugin
Note: fastify-plugin v2.3.0 and
newer, automatically adds .default property and a named export to the exported
plugin. Be sure to export default and export const myPlugin in your typings
to provide the best developer experience. For a complete example you can check
out
@fastify/swagger.
With those files completed, the plugin is now ready to be consumed by any TypeScript project!
The Fastify plugin system enables developers to decorate the Fastify instance, and the request/reply instances. For more information check out this blog post on Declaration Merging and Generic Inheritance.
Using a Plugin
Using a Fastify plugin in TypeScript is just as easy as using one in JavaScript.
Import the plugin with import/from and you're all set -- except there is one
exception users should be aware of.
Fastify plugins use declaration merging to modify existing Fastify type interfaces (check out the previous two examples for more details). Declaration merging is not very smart, meaning if the plugin type definition for a plugin is within the scope of the TypeScript interpreter, then the plugin types will be included regardless of if the plugin is being used or not. This is an unfortunate limitation of using TypeScript and is unavoidable as of right now.
However, there are a couple of suggestions to help improve this experience:
- Make sure the
no-unused-varsrule is enabled in ESLint and any imported plugin are actually being loaded. - Use a module such as depcheck or npm-check to verify plugin dependencies are being used somewhere in your project.
Note that using require will not load the type definitions properly and may
cause type errors.
TypeScript can only identify the types that are directly imported into code,
which means that you can use require inline with import on top. For example:
import 'plugin' // here will trigger the type augmentation.
fastify.register(require('plugin'))
import plugin from 'plugin' // here will trigger the type augmentation.
fastify.register(plugin)
Or even explicit config on tsconfig
{
"types": ["plugin"] // we force TypeScript to import the types
}
getDecorator<T>
Fastify's getDecorator<T> method retrieves decorators with enhanced type safety.
The getDecorator<T> method supports generic type parameters for enhanced type safety:
// Type-safe decorator retrieval
const usersRepository = fastify.getDecorator<IUsersRepository>('usersRepository')
const session = request.getDecorator<ISession>('session')
const sendSuccess = reply.getDecorator<SendSuccessFn>('sendSuccess')
Alternative to Module Augmentation
Decorators are typically typed via module augmentation:
declare module 'fastify' {
interface FastifyInstance {
usersRepository: IUsersRepository
}
interface FastifyRequest {
session: ISession
}
interface FastifyReply {
sendSuccess: SendSuccessFn
}
}
This approach modifies the Fastify instance globally, which may lead to conflicts and inconsistent behavior in multi-server setups or with plugin encapsulation.
Using getDecorator<T> allows limiting types scope:
serverOne.register(async function (fastify) {
const usersRepository = fastify.getDecorator<PostgreUsersRepository>(
'usersRepository'
)
fastify.decorateRequest('session', null)
fastify.addHook('onRequest', async (req, reply) => {
req.setDecorator('session', { user: 'Jean' })
})
fastify.get('/me', (request, reply) => {
const session = request.getDecorator<ISession>('session')
reply.send(session)
})
})
serverTwo.register(async function (fastify) {
const usersRepository = fastify.getDecorator<SqlLiteUsersRepository>(
'usersRepository'
)
fastify.decorateReply('sendSuccess', function (data) {
return this.send({ success: true })
})
fastify.get('/success', async (request, reply) => {
const sendSuccess = reply.getDecorator<SendSuccessFn>('sendSuccess')
await sendSuccess()
})
})
Bound Functions Inference
To save time, it is common to infer function types instead of writing them manually:
function sendSuccess (this: FastifyReply) {
return this.send({ success: true })
}
export type SendSuccess = typeof sendSuccess
However, getDecorator returns functions with the this context already bound,
meaning the this parameter disappears from the function signature.
To correctly type it, use the OmitThisParameter utility:
function sendSuccess (this: FastifyReply) {
return this.send({ success: true })
}
type BoundSendSuccess = OmitThisParameter<typeof sendSuccess>
fastify.decorateReply('sendSuccess', sendSuccess)
fastify.get('/success', async (request, reply) => {
const sendSuccess = reply.getDecorator<BoundSendSuccess>('sendSuccess')
await sendSuccess()
})
setDecorator<T>
Fastify's setDecorator<T> method provides enhanced type safety for updating request
decorators.
The setDecorator<T> method provides enhanced type safety for updating request
decorators:
fastify.decorateRequest('user', '')
fastify.addHook('preHandler', async (req, reply) => {
// Type-safe decorator setting
req.setDecorator<string>('user', 'Bob Dylan')
})
Type Safety Benefits
If the FastifyRequest interface does not declare the decorator, type assertions
are typically needed:
fastify.addHook('preHandler', async (req, reply) => {
(req as typeof req & { user: string }).user = 'Bob Dylan'
})
The setDecorator<T> method eliminates the need for explicit type assertions
while providing type safety:
fastify.addHook('preHandler', async (req, reply) => {
req.setDecorator<string>('user', 'Bob Dylan')
})
Code Completion In Vanilla JavaScript
Vanilla JavaScript can use the published types to provide code completion (e.g. Intellisense) by following the TypeScript JSDoc Reference.
For example:
/** @type {import('fastify').FastifyPluginAsync<{ optionA: boolean, optionB: string }>} */
module.exports = async function (fastify, { optionA, optionB }) {
fastify.get('/look', () => 'at me');
}
API Type System Documentation
This section is a detailed account of all the types available to you in Fastify version 3.x
All http, https, and http2 types are inferred from @types/node
Generics are documented by their default value as well as their constraint value(s). Read these articles for more information on TypeScript generics.
How to import
The Fastify API is powered by the fastify() method. In JavaScript you would
import it using const fastify = require('fastify'). In TypeScript it is
recommended to use the import/from syntax instead so types can be resolved.
There are a couple supported import methods with the Fastify type system.
import fastify from 'fastify'- Types are resolved but not accessible using dot notation
- Example:
import fastify from 'fastify'
const f = fastify()
f.listen({ port: 8080 }, () => { console.log('running') }) - Gain access to types with destructuring:
import fastify, { FastifyInstance } from 'fastify'
const f: FastifyInstance = fastify()
f.listen({ port: 8080 }, () => { console.log('running') }) - Destructuring also works for the main API method:
import { fastify, FastifyInstance } from 'fastify'
const f: FastifyInstance = fastify()
f.listen({ port: 8080 }, () => { console.log('running') })
import * as Fastify from 'fastify'- Types are resolved and accessible using dot notation
- Calling the main Fastify API method requires a slightly different syntax (see example)
- Example:
import * as Fastify from 'fastify'
const f: Fastify.FastifyInstance = Fastify.fastify()
f.listen({ port: 8080 }, () => { console.log('running') })
const fastify = require('fastify')- This syntax is valid and will import fastify as expected; however, types will not be resolved
- Example:
const fastify = require('fastify')
const f = fastify()
f.listen({ port: 8080 }, () => { console.log('running') }) - Destructuring is supported and will resolve types properly
const { fastify } = require('fastify')
const f = fastify()
f.listen({ port: 8080 }, () => { console.log('running') })
Generics
Many type definitions share the same generic parameters; they are all documented, in detail, within this section.
Most definitions depend on @types/node modules http, https, and http2
RawServer
Underlying Node.js server type
Default: http.Server
Constraints: http.Server, https.Server, http2.Http2Server,
http2.Http2SecureServer
Enforces generic parameters: RawRequest,
RawReply
RawRequest
Underlying Node.js request type
Default: RawRequestDefaultExpression
Constraints: http.IncomingMessage, http2.Http2ServerRequest
Enforced by: RawServer
RawReply
Underlying Node.js response type
Default: RawReplyDefaultExpression
Constraints: http.ServerResponse, http2.Http2ServerResponse
Enforced by: RawServer
Logger
Fastify logging utility
Default: FastifyLoggerOptions
Enforced by: RawServer
RawBody
A generic parameter for the content-type-parser methods.
Constraints: string | Buffer
Fastify
fastify< RawRequest, RawReply, Logger>(opts?: FastifyServerOptions): FastifyInstance
The main Fastify API method. By default creates an HTTP server. Utilizing
discriminant unions and overload methods, the type system will automatically
infer which type of server (http, https, or http2) is being created purely based
on the options based to the method (see the examples below for more
information). It also supports an extensive generic type system to allow the
user to extend the underlying Node.js Server, Request, and Reply objects.
Additionally, the Logger generic exists for custom log types. See the examples
and generic breakdown below for more information.
Example 1: Standard HTTP server
No need to specify the Server generic as the type system defaults to HTTP.
import fastify from 'fastify'
const server = fastify()
Check out the Learn By Example - Getting Started example for a more detailed http server walkthrough.
Example 2: HTTPS server
- Create the following imports from
@types/nodeandfastifyimport fs from 'node:fs'
import path from 'node:path'
import fastify from 'fastify' - Perform the following steps before setting up a Fastify HTTPS server
to create the
key.pemandcert.pemfiles:
openssl genrsa -out key.pem
openssl req -new -key key.pem -out csr.pem
openssl x509 -req -days 9999 -in csr.pem -signkey key.pem -out cert.pem
rm csr.pem
- Instantiate a Fastify https server and add a route:
const server = fastify({
https: {
key: fs.readFileSync(path.join(__dirname, 'key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'cert.pem'))
}
})
server.get('/', async function (request, reply) {
return { hello: 'world' }
})
server.listen({ port: 8080 }, (err, address) => {
if (err) {
console.error(err)
process.exit(0)
}
console.log(`Server listening at ${address}`)
}) - Build and run! Test your server out by querying with:
curl -k https://localhost:8080
Example 3: HTTP2 server
There are two types of HTTP2 server types, insecure and secure. Both require
specifying the http2 property as true in the options object. The https
property is used for creating a secure http2 server; omitting the https
property will create an insecure http2 server.
const insecureServer = fastify({ http2: true })
const secureServer = fastify({
http2: true,
https: {} // use the `key.pem` and `cert.pem` files from the https section
})
For more details on using HTTP2 check out the Fastify HTTP2 documentation page.
Example 4: Extended HTTP server
Not only can you specify the server type, but also the request and reply types. Thus, allowing you to specify special properties, methods, and more! When specified at server instantiation, the custom type becomes available on all further instances of the custom type.
import fastify from 'fastify'
import http from 'node:http'
interface customRequest extends http.IncomingMessage {
mySpecialProp: string
}
const server = fastify<http.Server, customRequest>()
server.get('/', async (request, reply) => {
const someValue = request.raw.mySpecialProp // TS knows this is a string, because of the `customRequest` interface
return someValue.toUpperCase()
})
Example 5: Specifying logger types
Fastify uses Pino logging library under the hood. Since
pino@7, all of it's properties can be configured via logger field when
constructing Fastify's instance. If properties you need aren't exposed, please
open an Issue to Pino or pass a
preconfigured external instance of Pino (or any other compatible logger) as
temporary fix to Fastify via the same field. This allows creating custom
serializers as well, see the Logging documentation for more info.
import fastify from 'fastify'
const server = fastify({
logger: {
level: 'info',
redact: ['x-userinfo'],
messageKey: 'message'
}
})
server.get('/', async (request, reply) => {
server.log.info('log message')
return 'another message'
})
fastify.HTTPMethods
Union type of: 'DELETE' | 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' | 'OPTIONS'
fastify.RawServerBase
Dependent on @types/node modules http, https, http2
Union type of: http.Server | https.Server | http2.Http2Server | http2.Http2SecureServer
fastify.RawServerDefault
Dependent on @types/node modules http
Type alias for http.Server
fastify.FastifyServerOptions< RawServer, Logger>
An interface of properties used in the instantiation of the Fastify server. Is
used in the main fastify() method. The RawServer and Logger
generic parameters are passed down through that method.
See the main fastify method type definition section for examples on instantiating a Fastify server with TypeScript.
fastify.FastifyInstance< RawServer, RawRequest, RequestGeneric, Logger>
Interface that represents the Fastify server object. This is the returned server
instance from the fastify() method. This type is an interface so it
can be extended via declaration
merging
if your code makes use of the decorate method.
Through the use of generic cascading, all methods attached to the instance inherit the generic properties from instantiation. This means that by specifying the server, request, or reply types, all methods will know how to type those objects.
Check out the main Learn by Example section for detailed guides, or the more simplified fastify method examples for additional details on this interface.