Skip to Content

类型提供器

类型提供器是 TypeScript 的一个特性,它使 Fastify 能够从内联 JSON Schema 中推断出类型信息。它们可以作为在路由中指定泛型参数的替代方案,并且减少了项目中为每个模式保持关联类型的需要。

提供器

官方类型提供器包遵循 @fastify/type-provider-{provider-name} 的命名约定。 社区提供的多个插件也已可用。

以下推断包受支持:

请参阅每个包的类型提供器包装器包:

Json Schema to Ts

以下代码设置了一个 json-schema-to-ts 类型提供器:

$ npm i @fastify/type-provider-json-schema-to-ts
import fastify from 'fastify' import { JsonSchemaToTsProvider } from '@fastify/type-provider-json-schema-to-ts' const server = fastify().withTypeProvider<JsonSchemaToTsProvider>() server.get('/route', { schema: { querystring: { type: 'object', properties: { foo: { type: 'number' }, bar: { type: 'string' }, }, required: ['foo', 'bar'] } } }, (request, reply) => { // 类型 Query = { foo: number, bar: string } const { foo, bar } = request.query // 安全类型! })

TypeBox

以下代码设置了一个TypeBox类型提供器:

$ npm i @fastify/type-provider-typebox
import fastify from 'fastify' import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' import { Type } from '@sinclair/typebox' const server = fastify().withTypeProvider<TypeBoxTypeProvider>() server.get('/route', { schema: { querystring: Type.Object({ foo: Type.Number(), bar: Type.String() }) } }, (request, reply) => { // type Query = { foo: number, bar: string } const { foo, bar } = request.query // 类型安全! })

有关如何使用TypeBox设置AJV的文档,请参阅 TypeBox 文档 

Zod

有关Zod类型提供器的说明,请参阅 官方文档 

命名空间类型提供器

提供器类型不会全局传播。在封装使用中,可以重新映射上下文以使用一个或多个提供器(例如,可以在同一应用程序中同时使用 typeboxjson-schema-to-ts)。

示例:

import Fastify from 'fastify' import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' import { JsonSchemaToTsProvider } from '@fastify/type-provider-json-schema-to-ts' import { Type } from '@sinclair/typebox' const fastify = Fastify() function pluginWithTypebox(fastify: FastifyInstance, _opts, done): void { fastify.withTypeProvider<TypeBoxTypeProvider>() .get('/', { schema: { body: Type.Object({ x: Type.String(), y: Type.Number(), z: Type.Boolean() }) } }, (req) => { const { x, y, z } = req.body // 类型安全 }); done() } function pluginWithJsonSchema(fastify: FastifyInstance, _opts, done): void { fastify.withTypeProvider<JsonSchemaToTsProvider>() .get('/', { schema: { body: { type: 'object', properties: { x: { type: 'string' }, y: { type: 'number' }, z: { type: 'boolean' } }, } } }, (req) => { const { x, y, z } = req.body // 类型安全 }); done() } fastify.register(pluginWithJsonSchema) fastify.register(pluginWithTypebox)

请注意,由于类型不会全局传播,在处理多个作用域时,目前无法避免在路由上进行多次注册,如下所示:

import Fastify from 'fastify' import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' import { Type } from '@sinclair/typebox' const server = Fastify().withTypeProvider<TypeBoxTypeProvider>() server.register(plugin1) // 错误 server.register(plugin2) // 正确 function plugin1(fastify: FastifyInstance, _opts, done): void { fastify.get('/', { schema: { body: Type.Object({ x: Type.String(), y: Type.Number(), z: Type.Boolean() }) } }, (req) => { // 在新的作用域中,再次调用 `withTypeProvider` 确保其正常工作 const { x, y, z } = req.body }); done() } function plugin2(fastify: FastifyInstance, _opts, done): void { const server = fastify.withTypeProvider<TypeBoxTypeProvider>() server.get('/', { schema: { body: Type.Object({ x: Type.String(), y: Type.Number(), z: Type.Boolean() }) } }, (req) => { // 正常工作 const { x, y, z } = req.body }); done() }

FastifyInstance 类型定义及 TypeProvider

在使用模块时,请结合 FastifyInstance 和 Type Provider 泛型。 请参阅下面的示例:

// index.ts import Fastify from 'fastify' import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' import { registerRoutes } from './routes' const server = Fastify().withTypeProvider<TypeBoxTypeProvider>() registerRoutes(server) server.listen({ port: 3000 })
// routes.ts import { Type } from '@sinclair/typebox' import { FastifyInstance, FastifyBaseLogger, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault } from 'fastify' import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox' type FastifyTypebox = FastifyInstance< RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>, FastifyBaseLogger, TypeBoxTypeProvider >; export function registerRoutes(fastify: FastifyTypebox): void { fastify.get('/', { schema: { body: Type.Object({ x: Type.String(), y: Type.Number(), z: Type.Boolean() }) } }, (req) => { // 可用 const { x, y, z } = req.body }); }