TypeScript
TypeScript
Fastify 框架是用原生 JavaScript 编写的,因此类型定义不容易维护;但是,从版本 2 及更高版本开始,维护人员和贡献者已经付出了巨大的努力来改进类型。
Fastify 版本 3 中更改了类型系统。新的类型系统引入了泛型约束和默认值,以及定义模式类型(例如请求体、查询字符串等)的新方法!随着团队致力于改进框架和类型定义的协同作用,API 的某些部分可能不会被类型化或类型化不正确。我们鼓励您 **贡献** 代码来帮助我们填补空白。在开始之前,请务必阅读我们的 CONTRIBUTING.md
文件,以确保一切顺利!
本节中的文档涵盖了 Fastify 版本 3.x 的类型。
插件可能包含也可能不包含类型。有关更多信息,请参阅 插件。我们鼓励用户发送拉取请求以改进类型支持。
🚨 不要忘记安装 @types/node
通过示例学习
学习 Fastify 类型系统的最佳方法是通过示例!以下四个示例应该涵盖了最常见的 Fastify 开发案例。在示例之后,将提供有关类型系统的更详细文档。
入门
此示例将帮助您使用 Fastify 和 TypeScript 快速入门。它将创建一个空白的 http Fastify 服务器。
创建一个新的 npm 项目,安装 Fastify,并安装 typescript 和 Node.js 类型作为对等依赖项
npm init -y
npm i fastify
npm i -D typescript @types/node将以下几行添加到
package.json
的"scripts"
部分{
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "node index.js"
}
}初始化一个 TypeScript 配置文件
npx tsc --init
或者使用其中一个 推荐的配置。
注意:将 tsconfig.json
中的 target
属性设置为 es2017
或更高版本,以避免 FastifyDeprecation 警告。
创建一个
index.ts
文件 - 此文件将包含服务器代码将以下代码块添加到您的文件中
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}`)
})运行
npm run build
- 这将编译index.ts
为index.js
,可以使用 Node.js 执行。如果您遇到任何错误,请在 fastify/help 中打开一个问题运行
npm run start
以运行 Fastify 服务器您应该在控制台中看到
Server listening at http://127.0.0.1:8080
使用
curl localhost:8080/ping
测试您的服务器,它应该返回pong
🏓
🎉 您现在拥有了一个可以工作的 Typescript Fastify 服务器!此示例演示了版本 3.x 类型系统的简单性。默认情况下,类型系统假定您正在使用 http
服务器。后面的示例将演示如何创建更复杂的服务器(例如 https
和 http2
),如何指定路由模式以及更多内容!
有关使用 TypeScript 初始化 Fastify 的更多示例(例如启用 HTTP2),请查看详细的 API 部分 此处
使用泛型
类型系统很大程度上依赖于泛型属性来提供最准确的开发体验。虽然有些人可能会发现开销有点繁琐,但权衡利弊是值得的!此示例将深入探讨为路由模式和位于路由级 request
对象上的动态属性实现泛型类型。
如果您没有完成前面的示例,请按照步骤 1-4 进行设置。
在
index.ts
中,定义三个接口IQuerystring
、IHeaders
和IReply
interface IQuerystring {
username: string;
password: string;
}
interface IHeaders {
'h-Custom': string;
}
interface IReply {
200: { success: boolean };
302: { url: string };
'4xx': { error: string };
}使用这三个接口,定义一个新的 API 路由并将其作为泛型传递。简写路由方法(即
.get
)接受一个泛型对象RouteGenericInterface
,其中包含五个命名属性:Body
、Querystring
、Params
、Headers
和Reply
。接口Body
、Querystring
、Params
和Headers
将通过路由方法传递到路由方法处理程序request
实例,而Reply
接口则传递到reply
实例。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 `logged in!`
})使用
npm run build
和npm run start
构建并运行服务器代码查询 API
curl localhost:8080/auth?username=admin&password=Password123!
它应该返回
logged in!
但是等等,还有更多!泛型接口也可用于路由级钩子方法中。通过添加
preValidation
钩子来修改之前的路由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 `logged in!`
})构建并运行,并使用
username
查询字符串选项设置为除admin
之外的任何内容进行查询。API 现在应该返回一个 HTTP 500 错误{"statusCode":500,"error":"Internal Server Error","message":"Must be admin"}
🎉 干得好,现在您可以为每个路由定义接口,并拥有严格类型的请求和响应实例。Fastify 类型系统的其他部分依赖于泛型属性。请务必参考下面的详细类型系统文档,以了解更多可用内容。
JSON 模式
要验证您的请求和响应,您可以使用 JSON 模式文件。如果您还不知道,为您的 Fastify 路由定义模式可以提高它们的吞吐量!查看 验证和序列化 文档以获取更多信息。
它还有在您的处理程序(包括预验证等)中使用定义类型的优势。
以下是一些实现此目的的方法。
Fastify 类型提供程序
Fastify 提供了两个包装 json-schema-to-ts
和 typebox
的包
以及一个由第三方提供的 zod
包装器,称为 fastify-type-provider-zod
它们简化了模式验证设置,您可以在 类型提供程序 页面中阅读更多相关信息。
以下是如何在没有类型提供程序的情况下使用 typebox
、json-schema-to-typescript
和 json-schema-to-ts
包设置模式验证。
TypeBox
一个用于同时构建类型和模式的有用库是 TypeBox。使用 TypeBox,您可以在代码中定义模式,并根据需要直接将其用作类型或模式。
当您想要在 fastify 路由中使用它来验证某些有效负载时,您可以按如下方式进行
在您的项目中安装
typebox
。npm i @sinclair/typebox
使用
Type
定义您需要的模式,并使用Static
创建相应的类型。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>在定义路由期间使用定义的类型和模式
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
在最后一个示例中,我们使用 Typebox 为我们的路由定义了类型和模式。许多用户将已经使用 JSON 模式来定义这些属性,幸运的是,有一种方法可以将现有的 JSON 模式转换为 TypeScript 接口!
如果您没有完成“入门”示例,请先返回并按照步骤 1-4 进行操作。
安装
json-schema-to-typescript
模块npm i -D json-schema-to-typescript
创建一个名为
schemas
的新文件夹,并添加两个文件headers.json
和querystring.json
。将以下模式定义复制并粘贴到相应的文件中{
"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"]
}向 package.json 添加一个
compile-schemas
脚本
{
"scripts": {
"compile-schemas": "json2ts -i schemas -o types"
}
}
json2ts
是 json-schema-to-typescript
中包含的 CLI 实用程序。schemas
是输入路径,types
是输出路径。5. 运行 npm run compile-schemas
。在 types
目录中应该创建了两个新文件。6. 更新 index.ts
以包含以下代码
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}`)
})
特别注意此文件顶部的导入。它可能看起来是多余的,但是您需要同时导入模式文件和生成的接口。
干得好!现在您可以同时使用 JSON 模式和 TypeScript 定义。
json-schema-to-ts
如果您不想从模式生成类型,而是想要直接在代码中使用它们,则可以使用包 json-schema-to-ts。
您可以将其安装为开发依赖项。
npm i -D json-schema-to-ts
在您的代码中,您可以像普通对象一样定义模式。但请注意,使其成为 const,如模块文档中所述。
const todo = {
type: 'object',
properties: {
name: { type: 'string' },
description: { type: 'string' },
done: { type: 'boolean' },
},
required: ['name'],
} as const; // don't forget to use const !
使用提供的类型 FromSchema
,您可以从模式构建类型并在处理程序中使用它。
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();
},
);
插件
Fastify 最显著的特性之一是其广泛的插件生态系统。插件类型得到完全支持,并利用了 声明合并 模式。此示例分为三个部分:创建 TypeScript Fastify 插件、为 Fastify 插件创建类型定义以及在 TypeScript 项目中使用 Fastify 插件。
创建 TypeScript Fastify 插件
初始化一个新的 npm 项目并安装所需的依赖项
npm init -y
npm i fastify fastify-plugin
npm i -D typescript @types/node向
package.json
文件的"scripts"
部分添加build
脚本,并向"types"
部分添加'index.d.ts'
{
"types": "index.d.ts",
"scripts": {
"build": "tsc -p tsconfig.json"
}
}初始化一个 TypeScript 配置文件
npx typescript --init
生成文件后,在
"compilerOptions"
对象中启用"declaration"
选项。{
"compilerOptions": {
"declaration": true
}
}创建一个
index.ts
文件 - 此文件将包含插件代码将以下代码添加到
index.ts
import { 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')运行
npm run build
以编译插件代码并生成 JavaScript 源文件和类型定义文件。现在插件已完成,您可以[发布到 npm]或在本地使用它。
您**无需**将插件发布到 npm 即可使用它。您可以将其包含在 Fastify 项目中,并像引用任何代码一样引用它!作为 TypeScript 用户,请确保声明覆盖存在于项目编译中包含的某个位置,以便 TypeScript 解释器可以处理它。
为 Fastify 插件创建类型定义
本插件指南适用于使用 JavaScript 编写的 Fastify 插件。此示例中概述的步骤用于为使用您插件的用户添加 TypeScript 支持。
初始化一个新的 npm 项目并安装所需的依赖项
npm init -y
npm i fastify-plugin创建两个文件
index.js
和index.d.ts
修改 package.json 以在
main
和types
属性下包含这些文件(名称不必显式为index
,但建议文件具有相同的名称){
"main": "index.js",
"types": "index.d.ts"
}打开
index.js
并添加以下代码// 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
})打开
index.d.ts
并添加以下代码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
**注意**:fastify-plugin v2.3.0 及更高版本会自动向导出的插件添加 .default
属性和命名导出。请确保在您的类型定义中使用 export default
和 export const myPlugin
以提供最佳的开发者体验。有关完整示例,您可以查看 @fastify/swagger。
完成这些文件后,插件现在就可以被任何 TypeScript 项目使用了!
Fastify 插件系统使开发人员能够装饰 Fastify 实例以及请求/回复实例。有关更多信息,请查看这篇关于 声明合并和泛型继承 的博文。
使用插件
在 TypeScript 中使用 Fastify 插件与在 JavaScript 中使用一样简单。使用 import/from
导入插件,一切就绪了——除了用户需要注意的一个例外。
Fastify 插件使用声明合并来修改现有的 Fastify 类型接口(查看前面两个示例以了解更多详细信息)。声明合并并不十分“智能”,这意味着如果插件的插件类型定义在 TypeScript 解释器的范围内,则无论插件是否正在使用,插件类型都将被包含。这是使用 TypeScript 的一个不幸的限制,目前无法避免。
但是,有一些建议可以帮助改善这种体验
- 确保在 ESLint 中启用了
no-unused-vars
规则,并且实际加载了任何导入的插件。 - 如果您启用了
@typescript-eslint/no-floating-promises
,请仔细检查您的 ESLint 配置是否包含allowForKnownSafePromises
属性,如typescript-eslint no-floating-promises allowForKnownSafePromises 文档
中所述
{
"rules": {
"@typescript-eslint/no-floating-promises": ["error", {
"allowForKnownSafePromises": [
{ "from": "package", "name": "FastifyInstance", "package": "fastify" },
{ "from": "package", "name": "FastifyReply", "package": "fastify" },
{ "from": "package", "name": "SafePromiseLike", "package": "fastify" },
]
}]
}
}
请注意,使用 require
将无法正确加载类型定义,并可能导致类型错误。TypeScript 只能识别直接导入到代码中的类型,这意味着您可以将 require
与顶部的 import
一起内联使用。例如
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)
甚至在 tsconfig 中进行显式配置
{
"types": ["plugin"] // we force TypeScript to import the types
}
在原生 JavaScript 中进行代码补全
原生 JavaScript 可以通过遵循 TypeScript JSDoc 参考,使用发布的类型来提供代码补全(例如 Intellisense)。
例如
/** @type {import('fastify').FastifyPluginAsync<{ optionA: boolean, optionB: string }>} */
module.exports = async function (fastify, { optionA, optionB }) {
fastify.get('/look', () => 'at me');
}
API 类型系统文档
本节详细介绍了 Fastify 3.x 版本中可用的所有类型。
所有 http
、https
和 http2
类型都从 @types/node
推断而来。
泛型 通过其默认值以及其约束值进行记录。阅读这些文章以了解更多关于 TypeScript 泛型的信息。
如何导入
Fastify API 由 fastify()
方法提供支持。在 JavaScript 中,您可以使用 const fastify = require('fastify')
导入它。在 TypeScript 中,建议改为使用 import/from
语法,以便可以解析类型。Fastify 类型系统支持几种导入方法。
import fastify from 'fastify'
类型已解析,但无法使用点表示法访问。
示例
import fastify from 'fastify'
const f = fastify()
f.listen({ port: 8080 }, () => { console.log('running') })使用解构访问类型
import fastify, { FastifyInstance } from 'fastify'
const f: FastifyInstance = fastify()
f.listen({ port: 8080 }, () => { console.log('running') })解构也适用于主 API 方法
import { fastify, FastifyInstance } from 'fastify'
const f: FastifyInstance = fastify()
f.listen({ port: 8080 }, () => { console.log('running') })
import * as Fastify from 'fastify'
类型已解析,并可以使用点表示法访问。
调用主 Fastify API 方法需要稍微不同的语法(请参阅示例)
示例
import * as Fastify from 'fastify'
const f: Fastify.FastifyInstance = Fastify.fastify()
f.listen({ port: 8080 }, () => { console.log('running') })
const fastify = require('fastify')
此语法有效,并将按预期导入 fastify;但是,类型将**不会**被解析。
示例
const fastify = require('fastify')
const f = fastify()
f.listen({ port: 8080 }, () => { console.log('running') })支持解构,并将正确解析类型。
const { fastify } = require('fastify')
const f = fastify()
f.listen({ port: 8080 }, () => { console.log('running') })
泛型
许多类型定义共享相同的泛型参数;它们都已在本节中详细记录。
大多数定义依赖于 @types/node
模块 http
、https
和 http2
RawServer
底层 Node.js 服务器类型
默认值:http.Server
约束:http.Server
、https.Server
、http2.Http2Server
、http2.Http2SecureServer
强制执行泛型参数:RawRequest
、RawReply
RawRequest
底层 Node.js 请求类型
默认值:RawRequestDefaultExpression
约束:http.IncomingMessage
、http2.Http2ServerRequest
由 RawServer
强制执行。
RawReply
底层 Node.js 响应类型
约束:http.ServerResponse
、http2.Http2ServerResponse
由 RawServer
强制执行。
Logger
Fastify 日志记录实用程序
由 RawServer
强制执行。
RawBody
内容类型解析器方法的泛型参数。
约束:string | Buffer
Fastify
fastify< RawRequest, RawReply, Logger>(opts?: FastifyServerOptions): FastifyInstance
主要的 Fastify API 方法。默认情况下创建 HTTP 服务器。利用判别联合和重载方法,类型系统将仅根据传递给方法的选项自动推断正在创建哪种类型的服务器(http、https 或 http2)(有关更多信息,请参阅下面的示例)。它还支持广泛的泛型类型系统,允许用户扩展底层的 Node.js Server、Request 和 Reply 对象。此外,Logger
泛型用于自定义日志类型。有关更多信息,请参阅下面的示例和泛型细分。
示例 1:标准 HTTP 服务器
无需指定 Server
泛型,因为类型系统默认为 HTTP。
import fastify from 'fastify'
const server = fastify()
查看“按示例学习” - 入门 示例以获取更详细的 http 服务器演练。
示例 2:HTTPS 服务器
- 从
@types/node
和fastify
创建以下导入import fs from 'fs'
import path from 'path'
import fastify from 'fastify' - 在设置 Fastify HTTPS 服务器之前,执行以下步骤以创建
key.pem
和cert.pem
文件
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
实例化 Fastify https 服务器并添加路由
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}`)
})构建并运行!通过查询测试您的服务器:
curl -k https://localhost:8080
示例 3:HTTP2 服务器
有两种类型的 HTTP2 服务器类型,不安全和安全。两者都需要在 options
对象中将 http2
属性指定为 true
。https
属性用于创建安全的 http2 服务器;省略 https
属性将创建不安全的 http2 服务器。
const insecureServer = fastify({ http2: true })
const secureServer = fastify({
http2: true,
https: {} // use the `key.pem` and `cert.pem` files from the https section
})
有关使用 HTTP2 的更多详细信息,请查看 Fastify 的 HTTP2 文档页面。
示例 4:扩展的 HTTP 服务器
您不仅可以指定服务器类型,还可以指定请求和回复类型。因此,允许您指定特殊属性、方法等!在服务器实例化时指定后,自定义类型将在所有后续自定义类型实例中可用。
import fastify from 'fastify'
import http from '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()
})
示例 5:指定日志记录器类型
Fastify 在后台使用 Pino 日志记录库。从 pino@7
开始,其所有属性都可以在构造 Fastify 实例时通过 logger
字段进行配置。如果您需要的属性未公开,请向 Pino
发起 Issue,或将 Pino(或任何其他兼容的日志记录器)的预配置外部实例作为临时修复程序传递给 Fastify(通过相同的字段)。这还允许创建自定义序列化程序,有关更多信息,请参阅 日志记录 文档。
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
以下类型的联合:'DELETE' | 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' | 'OPTIONS'
fastify.RawServerBase
依赖于 @types/node
模块 http
、https
、http2
以下类型的联合:http.Server | https.Server | http2.Http2Server | http2.Http2SecureServer
fastify.RawServerDefault
依赖于 @types/node
模块 http
http.Server
的类型别名
fastify.FastifyServerOptions< RawServer, Logger>
用于实例化 Fastify 服务器的属性接口。在主 fastify()
方法中使用。RawServer
和 Logger
泛型参数通过该方法传递。
有关使用 TypeScript 实例化 Fastify 服务器的示例,请参阅主 fastify 方法类型定义部分。
fastify.FastifyInstance< RawServer, RawRequest, RequestGeneric, Logger>
表示 Fastify 服务器对象的接口。这是从 fastify()
方法返回的服务器实例。此类型是一个接口,因此如果您的代码使用了 decorate
方法,则可以通过 声明合并 进行扩展。
通过使用泛型级联,附加到实例的所有方法都继承了实例化的泛型属性。这意味着通过指定服务器、请求或回复类型,所有方法都将知道如何对这些对象进行类型化。
查看主要的 通过示例学习 部分以获取详细指南,或查看更简化的 fastify 方法示例以获取有关此接口的其他详细信息。
请求
fastify.FastifyRequest< RequestGeneric, RawServer, RawRequest>
此接口包含 Fastify 请求对象的属性。此处添加的属性不考虑请求对象是什么类型(http 与 http2),也不考虑它正在服务哪个路由级别;因此,在 GET 请求内调用 request.body
不会抛出错误(但祝您好运发送带有正文的 GET 请求😉)。
如果您需要向 FastifyRequest
对象添加自定义属性(例如,使用[decorateRequest
][DecorateRequest]方法),则需要在此接口上使用声明合并。
在 FastifyRequest
部分提供了一个基本示例。有关更详细的示例,请查看“通过示例学习”部分:插件
示例
import fastify from 'fastify'
const server = fastify()
server.decorateRequest('someProp', 'hello!')
server.get('/', async (request, reply) => {
const { someProp } = request // need to use declaration merging to add this prop to the request interface
return someProp
})
// this declaration must be in scope of the typescript interpreter to work
declare module 'fastify' {
interface FastifyRequest { // you must reference the interface and not the type
someProp: string
}
}
// Or you can type your request using
type CustomRequest = FastifyRequest<{
Body: { test: boolean };
}>
server.get('/typedRequest', async (request: CustomRequest, reply: FastifyReply) => {
return request.body.test
})
fastify.RequestGenericInterface
Fastify 请求对象具有四个动态属性:body
、params
、query
和 headers
。它们的相应类型可以通过此接口分配。它是一个命名属性接口,使开发人员能够忽略他们不想指定的属性。所有省略的属性默认为 unknown
。相应的属性名称为:Body
、Querystring
、Params
、Headers
。
import fastify, { RequestGenericInterface } from 'fastify'
const server = fastify()
interface requestGeneric extends RequestGenericInterface {
Querystring: {
name: string
}
}
server.get<requestGeneric>('/', async (request, reply) => {
const { name } = request.query // the name prop now exists on the query prop
return name.toUpperCase()
})
如果您想查看使用此接口的详细示例,请查看“通过示例学习”部分:JSON 模式。
fastify.RawRequestDefaultExpression\<RawServer>
依赖于 @types/node
模块 http
、https
、http2
泛型参数 RawServer
默认为 RawServerDefault
如果 RawServer
的类型为 http.Server
或 https.Server
,则此表达式返回 http.IncomingMessage
,否则返回 http2.Http2ServerRequest
。
import http from 'http'
import http2 from 'http2'
import { RawRequestDefaultExpression } from 'fastify'
RawRequestDefaultExpression<http.Server> // -> http.IncomingMessage
RawRequestDefaultExpression<http2.Http2Server> // -> http2.Http2ServerRequest
回复
fastify.FastifyReply<RequestGeneric, RawServer, RawRequest, RawReply, ContextConfig>
此接口包含 Fastify 添加到标准 Node.js 回复对象的自定义属性。此处添加的属性不考虑回复对象是什么类型(http 与 http2)。
如果您需要向 FastifyReply 对象添加自定义属性(例如,使用 decorateReply
方法),则需要在此接口上使用声明合并。
在 FastifyReply
部分提供了一个基本示例。有关更详细的示例,请查看“通过示例学习”部分:插件
示例
import fastify from 'fastify'
const server = fastify()
server.decorateReply('someProp', 'world')
server.get('/', async (request, reply) => {
const { someProp } = reply // need to use declaration merging to add this prop to the reply interface
return someProp
})
// this declaration must be in scope of the typescript interpreter to work
declare module 'fastify' {
interface FastifyReply { // you must reference the interface and not the type
someProp: string
}
}
fastify.RawReplyDefaultExpression< RawServer>
依赖于 @types/node
模块 http
、https
、http2
泛型参数 RawServer
默认为 RawServerDefault
如果 RawServer
的类型为 http.Server
或 https.Server
,则此表达式返回 http.ServerResponse
,否则返回 http2.Http2ServerResponse
。
import http from 'http'
import http2 from 'http2'
import { RawReplyDefaultExpression } from 'fastify'
RawReplyDefaultExpression<http.Server> // -> http.ServerResponse
RawReplyDefaultExpression<http2.Http2Server> // -> http2.Http2ServerResponse
插件
Fastify 允许用户使用插件扩展其功能。插件可以是一组路由、服务器装饰器或任何其他内容。要激活插件,请使用 fastify.register()
方法。
在为 Fastify 创建插件时,建议使用 fastify-plugin
模块。此外,“通过示例学习”的 插件 部分提供了有关使用 TypeScript 和 Fastify 创建插件的指南。
fastify.FastifyPluginCallback< Options>
在 fastify.register()
方法中使用的接口方法定义。
fastify.FastifyPluginAsync< Options>
在 fastify.register()
方法中使用的接口方法定义。
fastify.FastifyPlugin< Options>
在 fastify.register()
方法中使用的接口方法定义。由于通用 FastifyPlugin
无法正确推断异步函数的类型,因此此文档已弃用,取而代之的是 FastifyPluginCallback
和 FastifyPluginAsync
。
fastify.FastifyPluginOptions
一个松散类型的对象,用于将 fastify.register()
的 options
参数约束为对象。在创建插件时,将其选项定义为此接口的扩展(interface MyPluginOptions extends FastifyPluginOptions
),以便可以将其传递给 register 方法。
注册
fastify.FastifyRegister(plugin: FastifyPluginCallback, opts: FastifyRegisterOptions)
fastify.FastifyRegister(plugin: FastifyPluginAsync, opts: FastifyRegisterOptions)
fastify.FastifyRegister(plugin: FastifyPlugin, opts: FastifyRegisterOptions)
此类型接口指定了 fastify.register()
方法的类型。类型接口返回一个函数签名,该签名具有一个底层泛型 Options
,该泛型默认为 FastifyPluginOptions。它在调用此函数时从 FastifyPlugin 参数推断此泛型,因此无需指定底层泛型。options 参数是插件选项与两个其他可选属性的交集:prefix: string
和 logLevel
:LogLevel。FastifyPlugin
已弃用,请改用 FastifyPluginCallback
和 FastifyPluginAsync
。
以下是在实际操作中选项推断的示例
const server = fastify()
const plugin: FastifyPluginCallback<{
option1: string;
option2: boolean;
}> = function (instance, opts, done) { }
server().register(plugin, {}) // Error - options object is missing required properties
server().register(plugin, { option1: '', option2: true }) // OK - options object contains required properties
有关在 Fastify 中创建 TypeScript 插件的更详细示例,请参阅“通过示例学习”的 插件 部分。
fastify.FastifyRegisterOptions
此类型是 Options
泛型与一个未导出的接口 RegisterOptions
的交集,该接口指定了两个可选属性:prefix: string
和 logLevel
:LogLevel。此类型也可以指定为返回先前描述的交集的函数。
日志记录器
有关指定自定义日志记录器的更多详细信息,请查看 指定日志记录器类型 示例。
fastify.FastifyLoggerOptions< RawServer, RawRequest, RawReply>
内部 Fastify 日志记录器的接口定义。它模拟了 Pino.js 日志记录器。在通过服务器选项启用时,请按照一般的 日志记录器 文档使用它。
fastify.FastifyLogFn
实现 Fastify 调用日志方法的两种方式的重载函数接口。此接口传递给 FastifyLoggerOptions 对象上的所有关联日志级别属性。
fastify.LogLevel
以下类型的联合:'info' | 'error' | 'debug' | 'fatal' | 'warn' | 'trace'
上下文
上下文类型定义类似于类型系统中其他高度动态的部分。路由上下文在路由处理程序方法中可用。
fastify.FastifyRequestContext
一个具有单个必需属性 config
的接口,该属性默认设置为 unknown
。可以使用泛型或重载来指定。
此类型定义可能不完整。如果您正在使用它并且可以提供有关如何改进定义的更多详细信息,我们强烈建议您在主要的 fastify/fastify 存储库中打开一个问题。感谢您提前提供帮助!
fastify.FastifyReplyContext
一个具有单个必需属性 config
的接口,该属性默认设置为 unknown
。可以使用泛型或重载来指定。
此类型定义可能不完整。如果您正在使用它并且可以提供有关如何改进定义的更多详细信息,我们强烈建议您在主要的 fastify/fastify 存储库中打开一个问题。感谢您提前提供帮助!
路由
Fastify 的核心原则之一是其路由功能。本节中定义的大多数类型都在 Fastify 实例 .route
和 .get/.post/.etc
方法的内部使用。
fastify.RouteHandlerMethod< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>
路由处理程序方法的类型声明。有两个参数,request
和 reply
,分别由 FastifyRequest
和 FastifyReply
键入。泛型参数传递给这些参数。该方法返回 void
或 Promise<any>
,分别用于同步和异步处理程序。
fastify.RouteOptions< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>
扩展 RouteShorthandOptions 并添加以下三个必需属性的接口
method
对应于单个 HTTPMethod 或 HTTPMethods 列表url
路由的字符串handler
路由处理程序方法,请参阅[RouteHandlerMethod][]了解更多详情
fastify.RouteShorthandMethod< RawServer, RawRequest, RawReply>
用于三种简写路由方法的重载函数接口,用于与 .get/.post/.etc
方法结合使用。
fastify.RouteShorthandOptions< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>
涵盖路由所有基本选项的接口。此接口上的每个属性都是可选的,它作为 RouteOptions 和 RouteShorthandOptionsWithHandler 接口的基础。
fastify.RouteShorthandOptionsWithHandler< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>
此接口向 RouteShorthandOptions 接口添加了一个必需属性 handler
,其类型为 RouteHandlerMethod
解析器
RawBody
一种泛型类型,可以是 string
或 Buffer
fastify.FastifyBodyParser< RawBody, RawServer, RawRequest>
用于指定主体解析器方法的函数类型定义。使用 RawBody
泛型指定要解析的主体类型。
fastify.FastifyContentTypeParser< RawServer, RawRequest>
用于指定主体解析器方法的函数类型定义。内容通过 RawRequest
泛型键入。
fastify.AddContentTypeParser< RawServer, RawRequest>
addContentTypeParser
方法的重载接口函数定义。如果将 parseAs
传递给 opts
参数,则定义使用[FastifyBodyParser][]作为 parser
参数;否则,它使用[FastifyContentTypeParser][].
fastify.hasContentTypeParser
一种用于检查特定内容类型的类型解析器是否存在的方法
错误
fastify.FastifyError
FastifyError 是一个自定义错误对象,包含状态代码和验证结果。
它扩展了 Node.js 的 Error
类型,并添加了两个额外的可选属性:statusCode: number
和 validation: ValidationResult[]
。
fastify.ValidationResult
路由验证在内部依赖于 Ajv,它是一个高性能的 JSON 模式验证器。
此接口传递给 FastifyError 的实例。
钩子
fastify.onRequestHookHandler< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>(request: FastifyRequest, reply: FastifyReply, done: (err?: FastifyError) => void): Promise\<unknown>| void
onRequest
是在请求生命周期中第一个执行的钩子。没有之前的钩子,下一个钩子将是 preParsing
。
注意:在 onRequest
钩子中,request.body 将始终为 null,因为主体解析发生在 preHandler
钩子之前。
fastify.preParsingHookHandler< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>(request: FastifyRequest, reply: FastifyReply, done: (err?: FastifyError) => void): Promise\<unknown>| void
preParsing
是在请求生命周期中第二个执行的钩子。之前的钩子是 onRequest
,下一个钩子将是 preValidation
。
注意:在 preParsing
钩子中,request.body 将始终为 null,因为主体解析发生在 preValidation
钩子之前。
注意:您还应该将 receivedEncodedLength
属性添加到返回的流中。此属性用于将请求有效负载与 Content-Length
标头值正确匹配。理想情况下,此属性应在每个接收到的块上更新。
fastify.preValidationHookHandler< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>(request: FastifyRequest, reply: FastifyReply, done: (err?: FastifyError) => void): Promise\<unknown>| void
preValidation
是在请求生命周期中第三个执行的钩子。之前的钩子是 preParsing
,下一个钩子将是 preHandler
。
fastify.preHandlerHookHandler< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>(request: FastifyRequest, reply: FastifyReply, done: (err?: FastifyError) => void): Promise\<unknown>| void
preHandler
是在请求生命周期中第四个执行的钩子。之前的钩子是 preValidation
,下一个钩子将是 preSerialization
。
fastify.preSerializationHookHandler< PreSerializationPayload, RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>(request: FastifyRequest, reply: FastifyReply, payload: PreSerializationPayload, done: (err: FastifyError | null, res?: unknown) => void): Promise\<unknown>| void
preSerialization
是在请求生命周期中第五个执行的钩子。之前的钩子是 preHandler
,下一个钩子将是 onSend
。
注意:如果有效负载是字符串、Buffer、流或 null,则不会调用该钩子。
fastify.onSendHookHandler< OnSendPayload, RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>(request: FastifyRequest, reply: FastifyReply, payload: OnSendPayload, done: (err: FastifyError | null, res?: unknown) => void): Promise\<unknown>| void
您可以使用 onSend
钩子更改有效负载。它是请求生命周期中第六个执行的钩子。之前的钩子是 preSerialization
,下一个钩子将是 onResponse
。
注意:如果您更改有效负载,则只能将其更改为字符串、Buffer、流或 null。
fastify.onResponseHookHandler< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>(request: FastifyRequest, reply: FastifyReply, done: (err?: FastifyError) => void): Promise\<unknown>| void
onResponse
是请求钩子生命周期中的第七个也是最后一个钩子。上一个钩子是 onSend
,没有下一个钩子。
onResponse 钩子在响应发送后执行,因此您将无法向客户端发送更多数据。但是,它对于将数据发送到外部服务(例如收集统计信息)很有用。
fastify.onErrorHookHandler< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>(request: FastifyRequest, reply: FastifyReply, error: FastifyError, done: () => void): Promise\<unknown>| void
如果需要执行一些自定义错误日志记录或在发生错误时添加一些特定的标头,此钩子很有用。
它不适用于更改错误,并且调用 reply.send 会抛出异常。
此钩子仅在 customErrorHandler 执行后且仅当 customErrorHandler 将错误发送回用户时才会执行(请注意,默认的 customErrorHandler 始终将错误发送回用户)。
注意:与其他钩子不同,不支持将错误传递给 done 函数。
fastify.onRouteHookHandler< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>(opts: RouteOptions &{path: string; prefix: string }): Promise\<unknown>| void
在注册新路由时触发。侦听器将路由选项对象作为唯一参数传递。该接口是同步的,因此侦听器不会传递回调。
fastify.onRegisterHookHandler< RawServer, RawRequest, RawReply, Logger>(instance: FastifyInstance, done: (err?: FastifyError) => void): Promise\<unknown>| void
在注册新插件并创建新的封装上下文时触发。该钩子将在注册的代码之前执行。
如果您正在开发一个需要知道何时形成插件上下文的插件,并且想要在该特定上下文中操作,则此钩子很有用。
注意:如果插件包装在 fastify-plugin 中,则不会调用此钩子。
fastify.onCloseHookHandler< RawServer, RawRequest, RawReply, Logger>(instance: FastifyInstance, done: (err?: FastifyError) => void): Promise\<unknown>| void
当调用 fastify.close() 停止服务器时触发。当插件需要“关闭”事件时(例如,关闭与数据库的打开连接)很有用。