如何在独立文件中为ElysiaJS处理器推断类型?
ElysiaJS拆分文件后处理器自动推断上下文类型的解决方案
问题背景
我在使用ElysiaJS开发API时,将代码拆分为auth.routes.ts、auth.handlers.ts和auth.dto.ts三个文件:
- 路由文件:定义路径、验证规则并绑定处理器函数
- DTO文件:导出验证规则对象
- 处理器文件:包含业务逻辑与数据库查询
拆分后遇到的问题:当处理器函数放在路由文件中时,Elysia能自动注入所有关联类型(比如验证后的body参数类型、数据库插件添加的db对象类型);但将处理器抽成独立文件后,直接使用Elysia默认的Context类型作为参数时,无法自动获取这些增强类型,只能手动构造类型解决,希望实现自动推断。
相关代码如下:
auth.routes.ts
const authRoutes = new Elysia({ prefix: '/auth' }) /** 注入数据库连接 */ .use(databaseConfig) /** 邮箱密码注册用户 */ .post('/register', registerWithEmailAndPassword, registerWithEmailAndPasswordDTO) export { authRoutes }
auth.dto.ts
import { t } from "elysia" export const registerWithEmailAndPasswordDTO = { body: t.Object({ email: t.String({ format: 'email' }), password: t.String({ minLength: 6 }), }) }
auth.handlers.ts
import { type Context } from "elysia" import Schema from "../../schema" import { hashPassword } from "../../utils/auth.utils" const { users } = Schema export const registerWithEmailAndPassword = async (context: Context): Promise<string> => { // 此处body和db的类型无法自动推断 const { set, body: { email, password }, db } = context // 业务逻辑代码 }
database.config.ts
// 创建数据库连接 const connection = connect({ host: process.env.DB_HOST, username: process.env.DB_USERNAME, password: process.env.DB_PASSWORD }) const db = drizzle(connection, { schema, logger }) const databaseConfig = new Elysia({ name: "databaseConfig" }) .decorate('db', () => db) export type dbType = typeof db export default databaseConfig
解决方案
要实现自动推断,核心是从路由文件导出经过插件和路由增强后的Elysia上下文类型,而非使用默认的Context。
步骤1:在路由文件中导出增强上下文类型
修改auth.routes.ts,导出当前Elysia实例的动态生成上下文类型:
import { Elysia } from 'elysia' import databaseConfig from './path/to/database.config' import { registerWithEmailAndPassword } from './auth.handlers' import { registerWithEmailAndPasswordDTO } from './auth.dto' const authRoutes = new Elysia({ prefix: '/auth' }) .use(databaseConfig) .post('/register', registerWithEmailAndPassword, registerWithEmailAndPasswordDTO) // 导出包含所有增强的上下文类型 export type AuthContext = typeof authRoutes['Context'] export { authRoutes }
步骤2:在处理器文件中使用导出的类型
修改auth.handlers.ts,导入刚才导出的AuthContext作为参数类型:
import { type AuthContext } from './auth.routes' import Schema from "../../schema" import { hashPassword } from "../../utils/auth.utils" const { users } = Schema export const registerWithEmailAndPassword = async (context: AuthContext): Promise<string> => { // 现在body和db的类型会被自动正确推断 const { set, body: { email, password }, db } = context // 业务逻辑代码 }
可选:单个路由的精准类型
如果需要为单个路由的处理器定义更精准的类型(仅包含该路由的body、params等信息),可以导出对应路由的上下文类型:
// 在auth.routes.ts中 export type RegisterRouteContext = typeof authRoutes['Route']['/auth/register']['POST']['Context']
随后在处理器中使用RegisterRouteContext即可获得该POST请求专属的上下文类型。
原理说明
Elysia的每个实例会根据挂载的插件、定义的路由规则和验证DTO,动态生成对应的Context类型。通过导出实例的Context属性,就能直接获取到包含所有增强特性(如数据库插件的db、验证后的body结构)的完整上下文类型,无需手动拼接类型。
内容的提问来源于stack exchange,提问作者Haseeb Burki
相关产品推荐
相关产品推荐

