如何在TypeScript中将外部接口属性展开到联合类型实现扁平结构?
实现TypeScript联合类型的扁平展开
可以通过类型映射结合交叉类型实现这种扁平化的联合类型,无需手动复制接口属性。具体实现方式如下:
步骤1:定义通用转换类型
首先创建一个通用类型,负责将包含type和data字段的类型展开为扁平结构:
type FlattenStorage<T extends { type: string; data: object }> = T['type'] extends infer Type ? Type extends string ? { type: Type } & T['data'] : never : never;
步骤2:转换原有联合类型
假设我们已有从外部包导入的接口和原联合类型,使用上述通用类型完成转换:
// 从外部包导入的接口(示例) interface PublicFileData { bucketName?: string; objectName?: string; } interface PrivateFileData { filePath?: string; accessToken?: string; } // 原有的嵌套结构联合类型 type OriginalStorage = | { type: "public"; data: PublicFileData } | { type: "private"; data: PrivateFileData }; // 转换后的扁平联合类型 type Storage = FlattenStorage<OriginalStorage>;
效果验证
此时Storage会被TypeScript自动推导为:
type Storage = | { type: "public"; bucketName?: string; objectName?: string } | { type: "private"; filePath?: string; accessToken?: string };
原理说明
- 利用条件类型的联合分发特性,联合类型的每个成员会被单独处理;
- 通过
infer关键字提取每个成员的type值和data对应的接口类型; - 使用交叉类型
&将type字段与data的所有属性合并,实现结构扁平化。
简洁写法
也可以直接在定义Storage时完成转换,省略单独的通用类型:
type Storage = OriginalStorage extends infer S ? S extends { type: infer Type; data: infer Data } ? { type: Type } & Data : never : never;
内容的提问来源于stack exchange,提问作者rostamiani
相关产品推荐
相关产品推荐

