如何将处理不同判别式联合类型的两个TypeScript函数合并为单个声明?
合并处理不同判别式联合类型的TypeScript函数
问题背景
给定以下两个判别式联合类型及对应的处理函数:
type T1M1 = { type: "m1" } type T1M2 = { type: "m2" } type T2M1 = { event: "e1" } type T2M2 = { event: "e2" } type Union1 = T1M1 | T1M2; type Union2 = T2M1 | T2M2; function f1<T extends Union1["type"], E extends Extract<Union1, { type:T }>> ( type: T, element: E ) {} function f2<T extends Union2["event"], E extends Extract<Union2, { type:T }>> ( type: T, element: E ) {}
请问是否存在方法能将上述f1和f2两个函数合并为单个函数声明?
解决方案
当然可以,以下是几种可行的实现方式:
方式一:泛型抽象判别式键
通过泛型参数抽象判别式的键名("type"或"event"),合并所有联合类型后,利用Extract工具类型做类型约束:
type T1M1 = { type: "m1" } type T1M2 = { type: "m2" } type T2M1 = { event: "e1" } type T2M2 = { event: "e2" } type Union1 = T1M1 | T1M2; type Union2 = T2M1 | T2M2; // 合并所有可能的联合类型 type AllUnions = Union1 | Union2; // 合并后的通用函数 function f<K extends keyof AllUnions, V extends AllUnions[K], E extends Extract<AllUnions, { [P in K]: V }>>( discriminantKey: K, discriminantValue: V, element: E ) {} // 合法调用示例 f("type", "m1", { type: "m1" }); f("event", "e2", { event: "e2" }); // 非法调用会触发类型报错 // f("type", "m1", { event: "e1" });
方式二:自动推导判别式类型
如果不需要显式传入判别式键,可以让TypeScript自动根据元素推导对应的判别式值类型,写法更简洁:
// 基于已定义的AllUnions类型 function f<E extends AllUnions>( discriminantValue: E[keyof E], element: E ) {} // 合法调用示例 f("m1", { type: "m1" }); f("e2", { event: "e2" }); // 非法调用会触发类型报错 // f("m1", { event: "e1" });
方式三:函数重载
如果希望保留原函数的参数结构(只传判别式值和元素),可以用函数重载实现,类型检查更直观:
// 重载签名1:处理Union1类型 function f<T extends Union1["type"]>(type: T, element: Extract<Union1, { type: T }>): void; // 重载签名2:处理Union2类型 function f<T extends Union2["event"]>(event: T, element: Extract<Union2, { event: T }>): void; // 通用实现签名 function f(discriminant: string, element: AllUnions) {} // 合法调用示例 f("m1", { type: "m1" }); f("e2", { event: "e2" }); // 非法调用会触发类型报错 // f("m1", { event: "e1" });
内容的提问来源于stack exchange,提问作者ilj
相关产品推荐
相关产品推荐

