如何在另一个模块中扩展TypeScript联合类型?
如何扩展TypeScript模块中的联合类型(解决ts(3200)重复标识符错误)
问题背景
核心模块@org/core导出了一个联合类型OptionType,尝试在@org/list模块中直接重新声明该类型以扩展新成员时,会触发ts(3200)重复标识符错误——这是因为TypeScript不允许在模块扩展中重新定义已存在的类型别名。
解决方案
方案1:修改核心模块(推荐,最优雅)
如果有权限修改@org/core,可以将原联合类型改为基于可扩展接口的结构,后续模块通过扩展接口实现类型扩展:
// @org/core // 原有基础类型 export type OptionAType = { type: 'a' }; export type OptionBType = { type: 'b' }; // 定义空接口作为扩展入口 export interface ExtendedOption {} // 核心联合类型包含基础类型和扩展接口 export type OptionType = OptionAType | OptionBType | ExtendedOption;
在@org/list中扩展接口:
// @org/list import type { ExtendedOption } from '@org/core'; // 自定义扩展类型 export type MyListOptionType = { type: 'list'; foo: string; bar: number }; // 扩展核心模块的ExtendedOption接口,自动合并到OptionType中 declare module '@org/core' { interface ExtendedOption extends MyListOptionType {} }
此时,任何导入@org/core中OptionType的代码,都会自动包含MyListOptionType。
方案2:无法修改核心模块时的替代方案
如果不能修改核心模块,只能在@org/list中导出新的扩展后类型,让用户从该模块导入:
// @org/list import type { OptionType as OriginalOptionType } from '@org/core'; // 自定义扩展类型 export type MyListOptionType = { foo: string; bar: number }; // 导出合并后的联合类型 export type OptionType = OriginalOptionType | MyListOptionType;
用户使用时,直接从@org/list导入扩展后的类型:
import type { OptionType } from '@org/list'; const demoOption: OptionType = { foo: 'example', bar: 123 };
关键原理
TypeScript仅支持接口、命名空间、枚举的声明合并,类型别名(type)无法直接合并。方案1通过引入可扩展接口绕开了这个限制,方案2则通过导出新类型实现扩展。
内容的提问来源于stack exchange,提问作者Tianzhen Lin
相关产品推荐
相关产品推荐

