跳至主要内容
版本:最新版本 (v5.0.x)

TypeScript

TypeScript

Fastify 框架是用原生 JavaScript 编写的,因此类型定义不容易维护;但是,从版本 2 及更高版本开始,维护人员和贡献者已经付出了巨大的努力来改进类型。

Fastify 版本 3 中更改了类型系统。新的类型系统引入了泛型约束和默认值,以及定义模式类型(例如请求体、查询字符串等)的新方法!随着团队致力于改进框架和类型定义的协同作用,API 的某些部分可能不会被类型化或类型化不正确。我们鼓励您 **贡献** 代码来帮助我们填补空白。在开始之前,请务必阅读我们的 CONTRIBUTING.md 文件,以确保一切顺利!

本节中的文档涵盖了 Fastify 版本 3.x 的类型。

插件可能包含也可能不包含类型。有关更多信息,请参阅 插件。我们鼓励用户发送拉取请求以改进类型支持。

🚨 不要忘记安装 @types/node

通过示例学习

学习 Fastify 类型系统的最佳方法是通过示例!以下四个示例应该涵盖了最常见的 Fastify 开发案例。在示例之后,将提供有关类型系统的更详细文档。

入门

此示例将帮助您使用 Fastify 和 TypeScript 快速入门。它将创建一个空白的 http Fastify 服务器。

  1. 创建一个新的 npm 项目,安装 Fastify,并安装 typescript 和 Node.js 类型作为对等依赖项

    npm init -y
    npm i fastify
    npm i -D typescript @types/node
  2. 将以下几行添加到 package.json"scripts" 部分

    {
    "scripts": {
    "build": "tsc -p tsconfig.json",
    "start": "node index.js"
    }
    }
  3. 初始化一个 TypeScript 配置文件

    npx tsc --init

    或者使用其中一个 推荐的配置

注意:将 tsconfig.json 中的 target 属性设置为 es2017 或更高版本,以避免 FastifyDeprecation 警告。

  1. 创建一个 index.ts 文件 - 此文件将包含服务器代码

  2. 将以下代码块添加到您的文件中

    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}`)
    })
  3. 运行 npm run build - 这将编译 index.tsindex.js,可以使用 Node.js 执行。如果您遇到任何错误,请在 fastify/help 中打开一个问题

  4. 运行 npm run start 以运行 Fastify 服务器

  5. 您应该在控制台中看到 Server listening at http://127.0.0.1:8080

  6. 使用 curl localhost:8080/ping 测试您的服务器,它应该返回 pong 🏓

🎉 您现在拥有了一个可以工作的 Typescript Fastify 服务器!此示例演示了版本 3.x 类型系统的简单性。默认情况下,类型系统假定您正在使用 http 服务器。后面的示例将演示如何创建更复杂的服务器(例如 httpshttp2),如何指定路由模式以及更多内容!

有关使用 TypeScript 初始化 Fastify 的更多示例(例如启用 HTTP2),请查看详细的 API 部分 此处

使用泛型

类型系统很大程度上依赖于泛型属性来提供最准确的开发体验。虽然有些人可能会发现开销有点繁琐,但权衡利弊是值得的!此示例将深入探讨为路由模式和位于路由级 request 对象上的动态属性实现泛型类型。

  1. 如果您没有完成前面的示例,请按照步骤 1-4 进行设置。

  2. index.ts 中,定义三个接口 IQuerystringIHeadersIReply

    interface IQuerystring {
    username: string;
    password: string;
    }

    interface IHeaders {
    'h-Custom': string;
    }

    interface IReply {
    200: { success: boolean };
    302: { url: string };
    '4xx': { error: string };
    }
  3. 使用这三个接口,定义一个新的 API 路由并将其作为泛型传递。简写路由方法(即 .get)接受一个泛型对象 RouteGenericInterface,其中包含五个命名属性:BodyQuerystringParamsHeadersReply。接口 BodyQuerystringParamsHeaders 将通过路由方法传递到路由方法处理程序 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!`
    })
  4. 使用 npm run buildnpm run start 构建并运行服务器代码

  5. 查询 API

    curl localhost:8080/auth?username=admin&password=Password123!

    它应该返回 logged in!

  6. 但是等等,还有更多!泛型接口也可用于路由级钩子方法中。通过添加 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!`
    })
  7. 构建并运行,并使用 username 查询字符串选项设置为除 admin 之外的任何内容进行查询。API 现在应该返回一个 HTTP 500 错误 {"statusCode":500,"error":"Internal Server Error","message":"Must be admin"}

🎉 干得好,现在您可以为每个路由定义接口,并拥有严格类型的请求和响应实例。Fastify 类型系统的其他部分依赖于泛型属性。请务必参考下面的详细类型系统文档,以了解更多可用内容。

JSON 模式

要验证您的请求和响应,您可以使用 JSON 模式文件。如果您还不知道,为您的 Fastify 路由定义模式可以提高它们的吞吐量!查看 验证和序列化 文档以获取更多信息。

它还有在您的处理程序(包括预验证等)中使用定义类型的优势。

以下是一些实现此目的的方法。

Fastify 类型提供程序

Fastify 提供了两个包装 json-schema-to-tstypebox 的包

以及一个由第三方提供的 zod 包装器,称为 fastify-type-provider-zod

它们简化了模式验证设置,您可以在 类型提供程序 页面中阅读更多相关信息。

以下是如何在没有类型提供程序的情况下使用 typeboxjson-schema-to-typescriptjson-schema-to-ts 包设置模式验证。

TypeBox

一个用于同时构建类型和模式的有用库是 TypeBox。使用 TypeBox,您可以在代码中定义模式,并根据需要直接将其用作类型或模式。

当您想要在 fastify 路由中使用它来验证某些有效负载时,您可以按如下方式进行

  1. 在您的项目中安装 typebox

    npm i @sinclair/typebox
  2. 使用 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>
  3. 在定义路由期间使用定义的类型和模式

    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. 如果您没有完成“入门”示例,请先返回并按照步骤 1-4 进行操作。

  2. 安装 json-schema-to-typescript 模块

    npm i -D json-schema-to-typescript
  3. 创建一个名为 schemas 的新文件夹,并添加两个文件 headers.jsonquerystring.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"]
    }
  4. 向 package.json 添加一个 compile-schemas 脚本

   {
"scripts": {
"compile-schemas": "json2ts -i schemas -o types"
}
}

json2tsjson-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 插件

  1. 初始化一个新的 npm 项目并安装所需的依赖项

    npm init -y
    npm i fastify fastify-plugin
    npm i -D typescript @types/node
  2. package.json 文件的 "scripts" 部分添加 build 脚本,并向 "types" 部分添加 'index.d.ts'

    {
    "types": "index.d.ts",
    "scripts": {
    "build": "tsc -p tsconfig.json"
    }
    }
  3. 初始化一个 TypeScript 配置文件

    npx typescript --init

    生成文件后,在 "compilerOptions" 对象中启用 "declaration" 选项。

    {
    "compilerOptions": {
    "declaration": true
    }
    }
  4. 创建一个 index.ts 文件 - 此文件将包含插件代码

  5. 将以下代码添加到 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')
  6. 运行 npm run build 以编译插件代码并生成 JavaScript 源文件和类型定义文件。

  7. 现在插件已完成,您可以[发布到 npm]或在本地使用它。

    您**无需**将插件发布到 npm 即可使用它。您可以将其包含在 Fastify 项目中,并像引用任何代码一样引用它!作为 TypeScript 用户,请确保声明覆盖存在于项目编译中包含的某个位置,以便 TypeScript 解释器可以处理它。

为 Fastify 插件创建类型定义

本插件指南适用于使用 JavaScript 编写的 Fastify 插件。此示例中概述的步骤用于为使用您插件的用户添加 TypeScript 支持。

  1. 初始化一个新的 npm 项目并安装所需的依赖项

    npm init -y
    npm i fastify-plugin
  2. 创建两个文件 index.jsindex.d.ts

  3. 修改 package.json 以在 maintypes 属性下包含这些文件(名称不必显式为 index,但建议文件具有相同的名称)

    {
    "main": "index.js",
    "types": "index.d.ts"
    }
  4. 打开 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
    })
  5. 打开 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 defaultexport const myPlugin 以提供最佳的开发者体验。有关完整示例,您可以查看 @fastify/swagger

完成这些文件后,插件现在就可以被任何 TypeScript 项目使用了!

Fastify 插件系统使开发人员能够装饰 Fastify 实例以及请求/回复实例。有关更多信息,请查看这篇关于 声明合并和泛型继承 的博文。

使用插件

在 TypeScript 中使用 Fastify 插件与在 JavaScript 中使用一样简单。使用 import/from 导入插件,一切就绪了——除了用户需要注意的一个例外。

Fastify 插件使用声明合并来修改现有的 Fastify 类型接口(查看前面两个示例以了解更多详细信息)。声明合并并不十分“智能”,这意味着如果插件的插件类型定义在 TypeScript 解释器的范围内,则无论插件是否正在使用,插件类型都将被包含。这是使用 TypeScript 的一个不幸的限制,目前无法避免。

但是,有一些建议可以帮助改善这种体验

{
"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" },
]
}]
}
}
  • 使用诸如 depchecknpm-check 之类的模块来验证插件依赖项是否在项目的某个地方被使用。

请注意,使用 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 版本中可用的所有类型。

所有 httphttpshttp2 类型都从 @types/node 推断而来。

泛型 通过其默认值以及其约束值进行记录。阅读这些文章以了解更多关于 TypeScript 泛型的信息。

如何导入

Fastify API 由 fastify() 方法提供支持。在 JavaScript 中,您可以使用 const fastify = require('fastify') 导入它。在 TypeScript 中,建议改为使用 import/from 语法,以便可以解析类型。Fastify 类型系统支持几种导入方法。

  1. 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') })
  2. 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') })
  3. 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 模块 httphttpshttp2

RawServer

底层 Node.js 服务器类型

默认值:http.Server

约束:http.Serverhttps.Serverhttp2.Http2Serverhttp2.Http2SecureServer

强制执行泛型参数:RawRequestRawReply

RawRequest

底层 Node.js 请求类型

默认值:RawRequestDefaultExpression

约束:http.IncomingMessagehttp2.Http2ServerRequest

RawServer 强制执行。

RawReply

底层 Node.js 响应类型

默认值:RawReplyDefaultExpression

约束:http.ServerResponsehttp2.Http2ServerResponse

RawServer 强制执行。

Logger

Fastify 日志记录实用程序

默认值:FastifyLoggerOptions

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 服务器
  1. @types/nodefastify 创建以下导入
    import fs from 'fs'
    import path from 'path'
    import fastify from 'fastify'
  2. 在设置 Fastify HTTPS 服务器之前,执行以下步骤以创建 key.pemcert.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
  1. 实例化 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}`)
    })
  2. 构建并运行!通过查询测试您的服务器:curl -k https://localhost:8080

示例 3:HTTP2 服务器

有两种类型的 HTTP2 服务器类型,不安全和安全。两者都需要在 options 对象中将 http2 属性指定为 truehttps 属性用于创建安全的 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 模块 httphttpshttp2

以下类型的联合:http.Server | https.Server | http2.Http2Server | http2.Http2SecureServer

fastify.RawServerDefault

源代码

依赖于 @types/node 模块 http

http.Server 的类型别名


fastify.FastifyServerOptions< RawServer, Logger>

源代码

用于实例化 Fastify 服务器的属性接口。在主 fastify() 方法中使用。RawServerLogger 泛型参数通过该方法传递。

有关使用 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 请求对象具有四个动态属性:bodyparamsqueryheaders。它们的相应类型可以通过此接口分配。它是一个命名属性接口,使开发人员能够忽略他们不想指定的属性。所有省略的属性默认为 unknown。相应的属性名称为:BodyQuerystringParamsHeaders

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 模块 httphttpshttp2

泛型参数 RawServer 默认为 RawServerDefault

如果 RawServer 的类型为 http.Serverhttps.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 模块 httphttpshttp2

泛型参数 RawServer 默认为 RawServerDefault

如果 RawServer 的类型为 http.Serverhttps.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 无法正确推断异步函数的类型,因此此文档已弃用,取而代之的是 FastifyPluginCallbackFastifyPluginAsync

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: stringlogLevelLogLevelFastifyPlugin 已弃用,请改用 FastifyPluginCallbackFastifyPluginAsync

以下是在实际操作中选项推断的示例

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: stringlogLevelLogLevel。此类型也可以指定为返回先前描述的交集的函数。


日志记录器

有关指定自定义日志记录器的更多详细信息,请查看 指定日志记录器类型 示例。

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>

源代码

路由处理程序方法的类型声明。有两个参数,requestreply,分别由 FastifyRequestFastifyReply 键入。泛型参数传递给这些参数。该方法返回 voidPromise<any>,分别用于同步和异步处理程序。

fastify.RouteOptions< RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig>

源代码

扩展 RouteShorthandOptions 并添加以下三个必需属性的接口

  1. method 对应于单个 HTTPMethodHTTPMethods 列表
  2. url 路由的字符串
  3. 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

一种泛型类型,可以是 stringBuffer

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: numbervalidation: 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() 停止服务器时触发。当插件需要“关闭”事件时(例如,关闭与数据库的打开连接)很有用。