TypeScript映射类型实现类Where子句提取命令对应依赖
TypeScript 基于Handler联合生成命令-依赖映射类型实现
问题场景
在纯类型层面开展TypeScript类型编程时,给定如下基础类型定义:
type Command<Type extends string> = { type: Type }; type Handler<Type extends string, Dependencies> = (cmd: Command<Type>, deps: Dependencies) => void; type CommandA = Command<"A">; type CommandB = Command<"B">; type MockServiceA = { foo: () => boolean }; type MockServiceB = { bar: () => boolean }; type HandlerA = Handler<"A", { someService: MockServiceA }>; type HandlerB = Handler<"B", { someService: MockServiceA; anotherService: MockServiceB }>; type HandlerSum = HandlerA | HandlerB; // 联合类型中可包含任意数量的Handler
需求说明
需要创建一个映射类型,生成由命令类型与对应依赖项构成的字典结构。
初始错误写法会返回所有依赖类型的联合结果,不符合预期:
type OnlyHalfwayThere = { [K in Parameters<HandlerSum>[0]["type"]]: Parameters<HandlerSum>[1]; // <--- 该写法会返回所有依赖类型的联合结果 };
需要实现类似Where子句的筛选逻辑:当Handler的第一个函数参数匹配当前遍历的键K时,提取该Handler的第二个函数参数,期望得到的结果结构如下:
type Outcome = { A: { someService: MockServiceA }; B: { someService: MockServiceA; anotherService: MockServiceB }; };
正确实现
类型定义
type CommandDepsMap<THandler extends Handler<string, any>> = { [K in Parameters<THandler>[0]["type"]]: THandler extends (cmd: Command<K>, deps: infer Deps) => void ? Deps : never; }; // 传入Handler联合即可得到目标结构 type Result = CommandDepsMap<HandlerSum>;
实现原理
- 核心依赖TypeScript分布式条件类型的默认行为:当条件类型的检查目标是联合类型时,TypeScript会自动遍历联合的每一个成员单独做类型匹配,最终将所有匹配结果合并为新的联合类型
- 遍历每个命令类型K时,将传入的Handler联合逐个匹配
(cmd: Command<K>, deps: infer Deps) => void结构,匹配成功就通过infer关键字提取对应依赖类型Deps - 不匹配当前K的Handler分支会返回
never,在类型合并时会被自动忽略,最终每个K只会对应到正确的单条依赖类型,不会出现所有依赖联合的错误结果
内容的提问来源于stack exchange,提问作者florian norbert bepunkt
相关产品推荐
相关产品推荐

