如何通过标签键与对应值创建Tagged Union(标记联合)实例
实现约束标记联合类型的泛型构造函数
要实现一个能正确关联标记联合类型的标签与对应值的泛型函数,你需要确保标签和值的类型是一一绑定的——原有的实现中,UnionKey<T>和UnionValue<T>会提取联合类型所有可能的标签和值的集合,导致标签和值之间没有关联,无法阻止错误的组合。
正确实现方案
type TagA = 'x' | 'y' | 'z'; type TagB = 'm' | 'n'; type UnionExampleA = | { tag: 'x', value: number} | { tag: 'y', value: [number, number]} | { tag: 'z', value: string} type UnionExampleB = | { tag: 'm', value: string} | { tag: 'n', value: null} // 提取联合类型T的所有标签值 type UnionTag<T> = T extends { tag: infer R } ? R : never; // 从联合类型T中筛选出标签为K的成员类型 type UnionMemberByTag<T, K extends UnionTag<T>> = T extends { tag: K } ? T : never; // 获取指定标签K对应的value类型 type UnionValueByTag<T, K extends UnionTag<T>> = UnionMemberByTag<T, K>['value']; function createUnionInstance<T, K extends UnionTag<T>>( tag: K, value: UnionValueByTag<T, K> ): UnionMemberByTag<T, K> { return { tag, value } as UnionMemberByTag<T, K>; }
使用示例
// 正确调用:自动推导标签对应的value类型 const a = createUnionInstance<UnionExampleA>('y', [15, 25]); // 显式指定标签类型(可选) const aExplicit = createUnionInstance<UnionExampleA, 'y'>('y', [15, 25]); const b = createUnionInstance<UnionExampleB>('m', '25'); // 以下错误调用均无法通过编译: // 标签不属于目标联合类型的标签集合 // const c = createUnionInstance<UnionExampleB>('y', [15, 25]); // 值的类型与标签不匹配 // const d = createUnionInstance<UnionExampleB>('m', [15, 25]);
实现说明
UnionTag<T>:通过条件类型的分布式特性,提取联合类型所有成员的tag字段值,得到标签的联合类型。UnionMemberByTag<T, K>:遍历联合类型的每个成员,筛选出tag等于指定值K的成员,确保返回的是该标签对应的具体类型。UnionValueByTag<T, K>:基于筛选出的成员类型,提取对应的value类型,保证标签和值的类型严格绑定。- 泛型函数
createUnionInstance通过两个泛型参数约束标签和值的对应关系,错误的标签值组合会在编译阶段直接被拦截,完全符合预期需求。
内容的提问来源于stack exchange,提问作者Alex Zhukovskiy
相关产品推荐
相关产品推荐

