如何用TypeScript泛型优化NestJS微服务嵌套对象的强类型调用
NestJS微服务通信的强类型约束优化
类型定义
我正在为NestJS微服务通信实现强类型约束,思路是通过一个对象定义所有微服务调用方式,包含对应的输入(args)和返回(result)类型,具体定义如下:
export type CompanyExpectedRoleAndCmd = { 'company': { 'find-unique': { input: number; result: string; }; 'find-many': { input: string; result: number; }; 'find-update': { input: string | number; result: number; }; }; 'company-employee': { 'find-unique': { input: string; result: Array<string>; }; }; }; export type EmployeeExpectedRoleAndCmd = { 'employee': { 'find-unique': { input: string; result: number; }; 'find-many': { input: number; result: string; }; 'find-update': { input: string; result: Array<number>; }; }; 'employee-provider': { 'find-unique': { input: number; result: Array<string>; }; }; }; export type ServiceTCP = { company: CompanyExpectedRoleAndCmd; employee: EmployeeExpectedRoleAndCmd; // 更多服务... };
现有实现逻辑
ServiceTCP定义了每个微服务的作用域,每个键对应的值是该微服务的所有交互方式。我已经实现了一套基础的强类型定义:
export type ServiceKeys = keyof ServiceTCP; export type ServiceRoleAndCmd<T extends ServiceKeys> = keyof ServiceTCP[T]; export type ServiceRole< T extends ServiceKeys, K extends ServiceRoleAndCmd<T>, > = keyof ServiceTCP[T][K]; export type ServiceCmd< T extends ServiceKeys, K extends ServiceRoleAndCmd<T>, C extends ServiceRole<T, K>, > = keyof ServiceTCP[T][K][C]; export type ServiceInput< T extends ServiceKeys, K extends ServiceRoleAndCmd<T>, C extends ServiceRole<T, K>, > = T extends keyof ServiceTCP ? K extends keyof ServiceTCP[T] ? C extends keyof ServiceTCP[T][K] ? ServiceTCP[T][K][C] extends { input: infer I } ? I : never : never : never : never; export type ServiceResult< T extends ServiceKeys, K extends ServiceRoleAndCmd<T>, C extends ServiceRole<T, K>, > = T extends keyof ServiceTCP ? K extends keyof ServiceTCP[T] ? C extends keyof ServiceTCP[T][K] ? ServiceTCP[T][K][C] extends { result: infer R } ? R : never : never : never : never; export type Pattern< T extends ServiceKeys, R extends ServiceRoleAndCmd<T>, C extends ServiceRole<T, R>, > = { role: R; cmd: C; };
存在的问题
这些类型定义可以正常工作,但TypeScript使用效率不高。比如我实现的微服务通信函数sendMessageTCP:
const sendMessageTCP = async < T extends ServiceKeys, R extends ServiceRoleAndCmd<T>, C extends ServiceRole<T, R> >( pattern: Pattern<T, R, C>, input: ServiceInput<T, R, C>, ): Promise<ServiceResult<T, R, C>> => { /// 示例中手动类型转换 return {} as ServiceResult<T, R, C>; };
调用时必须指定每一层泛型参数,冗余度很高:
const result = sendMessageTCP<'company', 'company', 'find-many'>( { role: 'company', cmd: 'find-many' }, 'string', ); // result 类型为 string
我希望优化后只需指定服务键(如'company'),就能自动推导其他类型,同时保持输入、返回值的强类型约束,调用方式如下:
const result = sendMessageTCP<'company'>( { role: 'company', cmd: 'find-many' }, 'string', ); // result 类型为 string
内容的提问来源于stack exchange,提问作者nerap
相关产品推荐
相关产品推荐

