如何在TypeScript中基于请求类自动推导对应响应类型?
TypeScript实现请求响应类型自动推导方案
TypeScript完全支持这种需求,不需要依赖局限于已知类型的条件类型,以下提供两种可靠的实现方案:
方案一:通过静态属性关联请求与响应类型(推荐)
这种方式不依赖类命名规则,扩展性更强,类型推导更可靠:
// 基础抽象类 abstract class Request { // 静态属性用于关联对应的响应类型 static readonly ResponseType: typeof Response; } abstract class Response {} // 示例请求/响应子类,关联对应关系 class Example1Request extends Request { static readonly ResponseType = Example1Response; } class Example1Response extends Response {} class Example2Request extends Request { static readonly ResponseType = Example2Response; } class Example2Response extends Response {} // 实现query函数 function query<T extends Request>(request: T): InstanceType<T['constructor']['ResponseType']> { // 这里编写实际请求逻辑,比如发送请求、处理响应 return {} as InstanceType<T['constructor']['ResponseType']>; } // 使用示例 const req1 = new Example1Request(); const res1 = query(req1); // res1 类型自动推导为 Example1Response const req2 = new Example2Request(); const res2 = query(req2); // res2 类型自动推导为 Example2Response
方案二:基于类名后缀的字符串替换推导
如果严格遵循XXXRequest/XXXResponse的命名规范,可以利用TypeScript 4.1+支持的字符串字面量替换特性实现:
// 基础抽象类 abstract class Request {} abstract class Response {} // 示例请求/响应子类 class Example1Request extends Request {} class Example1Response extends Response {} class Example2Request extends Request {} class Example2Response extends Response {} // 扩展全局类型,让TypeScript识别自定义的响应类 declare global { interface Window { Example1Response: typeof Example1Response; Example2Response: typeof Example2Response; } } // 定义请求到响应的类型映射工具 type RequestToResponse<T extends Request> = T extends { constructor: { name: `${infer Prefix}Request` } } ? `${Prefix}Response` extends keyof Window ? InstanceType<Window[`${Prefix}Response`]> : never : never; // 实现query函数 function query<T extends Request>(): RequestToResponse<T> { // 实际请求逻辑 return {} as RequestToResponse<T>; } // 使用示例 const res1 = query<Example1Request>(); // res1 类型为 Example1Response const req2 = new Example2Request(); const res2 = query<typeof req2>(); // res2 类型为 Example2Response
两种方案都不需要硬编码已知类型,新增请求/响应子类时无需修改query函数的类型定义,完全满足扩展性需求。
内容的提问来源于stack exchange,提问作者Matthias Hryniszak
相关产品推荐
相关产品推荐

