TypeScript中hydrate函数后如何保留正确的类型信息
TypeScript db方法依赖注入后类型丢失修复方案
问题根因
- 预先定义的
WithDb类型将所有方法签名宽泛化为(db: any) => (...args: any) => any,提前抹除了每个业务方法的精确参数、返回值类型,后续映射类型无法获取原始方法的类型信息 Object.keys默认返回string[]类型,reduce初始值传入空对象时,TypeScript默认将累加器类型推导为{},动态赋值计算属性时不会自动匹配目标类型,最终导致类型信息完全丢失
修复后完整代码
// 可替换为你实际的db实例类型 type Db = any; const dbMethods = { getModerators: (db: Db) => (chatId: string) => Promise.resolve([111]), getRooms: (db: Db) => (accountId: string) => Promise.resolve([222]) } // 映射类型:传入原始db方法集合,生成注入db后的hydrated方法集合类型 type HydratedMethods<T extends Record<string, (db: Db) => any>> = { [K in keyof T]: ReturnType<T[K]> } // 提前初始化你的db实例 const db = {} as Db; // 遍历生成hydrated方法集合,通过最小类型断言保证类型正确推导 const hydrated = Object.keys(dbMethods).reduce((acc, methodKey) => { const key = methodKey as keyof typeof dbMethods; acc[key] = dbMethods[key](db); return acc; }, {} as HydratedMethods<typeof dbMethods>) // 调用时类型完全正常,自动做入参校验、返回值推导 const rooms = hydrated.getRooms('some accountId') // 自动推导为Promise<number[]>类型 // hydrated.getRooms(123) 会触发类型报错,提示参数类型不匹配
关键说明
- 移除了无意义的宽泛中间类型,所有类型直接从
dbMethods的原始字面量类型推导,完整保留每个业务方法的签名信息 - 仅在遍历键、reduce初始值位置做最小必要的类型断言,避免TypeScript默认的宽泛推导覆盖目标类型
- 后续新增db方法时,不需要额外修改类型定义,
hydrated对象会自动推导出新增方法的类型,适配数百个方法的规模无额外维护成本
内容的提问来源于stack exchange,提问作者Novellizator
相关产品推荐
相关产品推荐

