如何将TypeScript可辨识联合类型动态映射为另一可辨识联合类型
TypeScript可辨识联合类型的动态映射方案
先看我们的原始可辨识联合类型定义:
type Shape = Triangle | Rectangle; interface Triangle { type: "triangle"; base: number; height: number; } interface Rectangle { type: "rectangle"; width: number; height: number; }
要把它动态转换成如下的ShapeMessage联合类型:
type ShapeMessage = | { contentType: "application/vnd.shape.triangle"; content: { base: number; height: number; }; } | { contentType: "application/vnd.shape.rectangle"; content: { width: number; height: number; }; };
可以通过TypeScript的泛型映射类型+条件类型实现完全动态的转换,不需要手动逐个定义:
// 定义通用的转换泛型 type ShapeToMessage<S extends { type: string }> = { // 遍历联合类型中所有的type字面量值 [K in S['type']]: { // 用模板字面量生成指定格式的contentType contentType: `application/vnd.shape.${K}`; // 提取对应type的子类型,再去掉type属性作为content content: Omit<Extract<S, { type: K }>, 'type'>; }; // 最后将映射后的对象类型转为联合类型 }[S['type']]; // 生成目标类型 type ShapeMessage = ShapeToMessage<Shape>;
代码解释:
S extends { type: string }约束泛型参数必须是带有type辨识属性的类型S['type']提取出联合类型中所有type的字面量值(这里就是"triangle" | "rectangle")- 映射类型
[K in S['type']]为每个type值生成对应的消息结构 Extract<S, { type: K }>从联合类型中筛选出type等于K的子类型Omit<..., 'type'>移除子类型中的type属性,只保留业务字段作为content- 最后通过
[S['type']]索引访问,把映射后的对象类型拆解成联合类型,和手动定义的ShapeMessage完全一致
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

