TypeScript导出Hono路由typeof类型时导入为any的问题求助
如何正确导出Hono路由生成的typeof复杂类型供其他包使用?
我在TypeScript模块中通过typeof导出Hono路由生成的复杂类型,但其他包导入该类型时始终显示为any。相关代码与配置如下:
问题代码示例
控制器文件 controller/createProfile.ts
import { z } from 'zod'; import { zValidator } from '@hono/zod-validator'; const createProfileBody = z.object({ id: z.string({ required_error: 'Id is required.' }), username: z.string({ required_error: 'User name is required.' }), firstname: z.string({ required_error: 'First name is required' }), lastname: z.optional(z.string()), avatar: z.optional(z.string()), }); const route = app.post('/', zValidator('json', createProfileBody), async c => { // ... 路由逻辑 }); export type CreateProfileType = typeof route;
类型导出文件 types.d.ts
export * from './controller/createProfile';
项目tsconfig配置
{ "include": ["src/**/*.ts"], "compilerOptions": { "baseUrl": "src", "target": "esnext", "module": "esnext", "lib": ["esnext"], "resolveJsonModule": true, "moduleResolution": "node", "allowJs": true, "checkJs": false, "isolatedModules": true, "allowSyntheticDefaultImports": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true } }
问题现象
- 本地编辑器中能看到
route的完整类型:Hono<{ Bindings: Binding; }, Schema<"post", "/", { json: { lastname?: string | undefined; avatar?: string | undefined; id: string; username: string; firstname: string; }; }, ReturnType>> - 但tsc生成的声明文件中
route被推断为any:export declare const route: any; export type CreateProfileType = typeof route; - 手动给
route添加显式类型注解后,导出的类型恢复正常。
解决方案
1. 调整TypeScript编译配置
开启类型声明生成,并根据项目需求调整isolatedModules:
{ "compilerOptions": { // ... 其他原有配置 "declaration": true, // 启用类型声明文件生成 "declarationMap": true, // 生成类型映射,方便调试 "isolatedModules": false // 若项目不需要独立模块编译,可关闭此选项 } }
isolatedModules会强制单文件编译,导致TypeScript无法完整保留Hono路由的复杂泛型类型,关闭后能让编译器完整推断路由类型。
2. 显式提取路由Schema类型
避免直接依赖typeof route,先从Hono类型工具中提取路由的Schema定义:
// controller/createProfile.ts import { z } from 'zod'; import { zValidator } from '@hono/zod-validator'; import type { Hono, Schema } from 'hono'; const createProfileBody = z.object({ id: z.string({ required_error: 'Id is required.' }), username: z.string({ required_error: 'User name is required.' }), firstname: z.string({ required_error: 'First name is required' }), lastname: z.optional(z.string()), avatar: z.optional(z.string()), }); // 显式定义路由的Schema类型 type CreateProfileRouteSchema = Schema< "post", "/", { json: z.infer<typeof createProfileBody> }, Profile // 替换为你的路由返回类型 >; // 给路由方法传入预定义的Schema类型 const route = app.post<CreateProfileRouteSchema>( '/', zValidator('json', createProfileBody), async c => { // ... 路由逻辑 } ); export type CreateProfileType = typeof route;
这种方式让TypeScript明确识别路由的泛型参数,生成声明文件时不会丢失类型信息。
3. 手动添加路由类型注解(快速修复)
如你已经尝试的那样,直接给route变量添加完整的类型注解:
const route: Hono< { Bindings: Binding }, Schema<'post','/', { json: z.infer<typeof createProfileBody> }, Profile > > = app.post('/', zValidator('json', createProfileBody), async c => { // ... 路由逻辑 }); export type CreateProfileType = typeof route;
4. 验证Hono类型完整性
如果开启了skipLibCheck,可尝试临时关闭它,检查是否是Hono类型定义冲突导致的问题。若关闭后类型恢复正常,建议更新Hono到最新版本,确保其类型定义完整兼容当前TypeScript版本。
验证方法
修改配置或代码后,重新执行编译命令,查看生成的.d.ts文件,确认route的类型不再是any,而是完整的Hono泛型类型。此时其他包导入CreateProfileType即可获取正确的类型信息。
内容的提问来源于stack exchange,提问作者JonasLevin
相关产品推荐
相关产品推荐

