TypeScript中匹配字符串与对象联合类型并保留值的实现
实现带关联值枚举的类型安全匹配函数
针对从Rust枚举转换而来的TypeScript类型(字符串或单键对象的联合),我们可以通过分布式条件类型和联合函数类型实现类型安全的matchEnum函数,让回调参数的类型自动匹配对应枚举项的关联值。
步骤1:定义类型工具
先通过辅助类型拆解枚举结构,提取键和对应的关联值:
// 提取枚举类型的所有可能键 type EnumKeys<E> = E extends string ? E : E extends { [K in infer Key]: unknown } ? Key : never; // 根据键获取对应的关联值类型,无关联值时为undefined type EnumValueForKey<E, K extends EnumKeys<E>> = E extends { [_ in K]: infer V } ? V : undefined; // 生成匹配回调的联合函数类型,每个键对应一个准确的签名 type EnumMatcher<E, RT> = { [K in EnumKeys<E>]: (key: K, value: EnumValueForKey<E, K>) => RT; }[EnumKeys<E>];
步骤2:实现matchEnum函数
基于上述类型工具编写函数逻辑:
export function matchEnum<E, RT>(enm: E, matcher: EnumMatcher<E, RT>): RT { if (typeof enm === 'string') { // 处理无关联值的字符串枚举项 return matcher(enm as EnumKeys<E>, undefined as EnumValueForKey<E, typeof enm>); } else { // 处理带关联值的单键对象枚举项 const [key] = Object.keys(enm) as [EnumKeys<E>]; return matcher(key, enm[key] as EnumValueForKey<E, typeof key>); } }
用法示例
用你提供的枚举类型测试:
type StructT = { num: number }; type EnumWithValues = ( { "TupleVal": [number, number] } | { "StructVal": StructT } | "SimpleVal" ); // 无关联值的情况 const simpleVal: EnumWithValues = "SimpleVal"; matchEnum(simpleVal, (key, args) => { // key类型:"SimpleVal",args类型:undefined console.log(`类型:${key},无关联值`); }); // 元组关联值的情况 const tupleVal: EnumWithValues = { TupleVal: [10, 20] }; matchEnum(tupleVal, (key, args) => { // key类型:"TupleVal",args类型:[number, number] console.log(`类型:${key},第一个值:${args[0]}`); }); // 结构体关联值的情况 const structVal: EnumWithValues = { StructVal: { num: 30 } }; matchEnum(structVal, (key, args) => { // key类型:"StructVal",args类型:StructT console.log(`类型:${key},num值:${args.num}`); });
这个实现会让TypeScript自动推断每个枚举项对应的参数类型,避免了之前版本中args始终是联合类型的问题。
内容的提问来源于stack exchange,提问作者Jesse
相关产品推荐
相关产品推荐

