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

类型提供程序

类型提供程序

类型提供程序是仅限 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) => {

// type Query = { foo: number, bar: string }
const { foo, bar } = request.query // type safe!
})

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 // type safe!
})

另请参阅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 // type safe
});
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 // type safe
});
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) // wrong
server.register(plugin2) // correct

function plugin1(fastify: FastifyInstance, _opts, done): void {
fastify.get('/', {
schema: {
body: Type.Object({
x: Type.String(),
y: Type.Number(),
z: Type.Boolean()
})
}
}, (req) => {
// it doesn't work! in a new scope needs to call `withTypeProvider` again
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) => {
// works
const { x, y, z } = req.body
});
done()
}

FastifyInstance + 类型提供程序的类型定义

在使用模块时,必须使用带有类型提供程序泛型的FastifyInstance。请参阅以下示例

// 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) => {
// works
const { x, y, z } = req.body
});
}