TypeScript如何基于构造传入的参数解析器生成对应类型约束?
解法
你可以通过TS的映射类型和类型推断实现需求,完整的类型定义如下:
class QueryParamHandler<T> { parse(v: string): T { throw new Error("未实现") } stringify(v: T): string { throw new Error("未实现") } } // 基础类型解析器实例定义 const stringParser: QueryParamHandler<string> = new QueryParamHandler(); const numberParser: QueryParamHandler<number> = new QueryParamHandler(); const booleanParser: QueryParamHandler<boolean> = new QueryParamHandler(); const dateParser: QueryParamHandler<Date> = new QueryParamHandler(); // 可复用的类型提取别名,也可以直接写在方法入参/返回值位置 type ExtractHandlerTypes<TP extends Record<string, QueryParamHandler<any>>> = Partial<{ [K in keyof TP]: TP[K] extends QueryParamHandler<infer T> ? T : never }> // 核心MyCoolHandler实现 class MyCoolHandler<TP extends Record<string, QueryParamHandler<any>>> { constructor(private handlers: TP) {} parse(query: string): ExtractHandlerTypes<TP> { // 这里写你的解析逻辑 return {} as any } stringify(vals: ExtractHandlerTypes<TP>): string { // 这里写你的序列化逻辑 return '' } }
效果验证
和你期望的运行效果完全匹配:
const handler = new MyCoolHandler({ str: stringParser, from: dateParser }); handler.stringify({}); // 正常通过 handler.stringify({ str: 'qqq' }); // 正常通过 handler.stringify({ numb: 3 }); // TS报错:对象字面量只能指定已知属性,"numb" 不在类型中 handler.stringify({ from: 'qq' }); // TS报错:类型"string"不能分配给类型"Date" const params = handler.parse('str=&from=2021-09-07') console.log(params.str) // 正常读取,类型为string | undefined console.log(params.numb) // TS报错:类型上不存在属性"numb"
实现逻辑说明
- 给
MyCoolHandler定义泛型参数TP,约束为键是字符串、值是QueryParamHandler实例的对象,用来承接构造函数传入的解析器集合 - 用
infer关键字推断每个QueryParamHandler对应的泛型参数类型,搭配映射类型生成和传入解析器键名一一对应的对象类型 - 用
Partial工具类型把所有属性设为可选,满足字段允许为undefined的要求
内容的提问来源于stack exchange,提问作者Anton Karpov
相关产品推荐
相关产品推荐

