如何从合并后的TypeScript声明中提取单个原始接口类型?
从合并后的TypeScript接口中提取原始单个接口类型
问题背景
TypeScript中接口会自动合并,比如两个第三方库的声明文件分别在declare global {}中定义了Box接口:
// lib1.d.ts(第三方库1) declare global { interface Box { height: number; width: number; // 其他30+属性 } } // lib2.d.ts(第三方库2) declare global { interface Box { scale: number; // 其他30+属性 } }
合并后的Box包含所有属性,大部分场景可以正常使用,但特殊场景下需要仅使用第一个库的原始Box类型,又不想复制声明(需同步后续变更)或用Omit(需手动列出所有要排除的属性)。
解决方案:利用模块隔离获取原始类型
核心思路是创建单独的类型模块,仅引入包含目标原始接口的第三方库,此时该模块内的Box就是未合并的原始类型,再将其导出供其他代码使用:
- 创建类型文件(比如
src/types/original-box.ts):
// 仅引入包含第一个Box声明的第三方库 import 'lib1'; // 导出该库的原始Box类型,命名为OriginalBox以便区分 export type OriginalBox = Box;
- 在需要使用原始类型的代码中导入:
import type { OriginalBox } from './types/original-box'; // 此处的OriginalBox仅包含lib1中定义的属性 const box: OriginalBox = { height: 5, width: 6 };
原理说明
TypeScript的全局声明合并仅在相同作用域内生效。当我们在单独模块中仅引入lib1时,该模块的全局作用域只会加载lib1的Box声明,不会加载lib2的,因此此时的Box就是未合并的原始类型。
备选方案:使用类型工具(仅当属性固定时)
如果无法通过模块隔离实现(比如两个声明来自同一个库),可以利用Pick工具类型手动指定需要保留的属性,但这种方式需要维护属性列表,仅适合属性变动较少的场景:
// 手动指定lib1中的所有属性 type OriginalBox = Pick<Box, 'height' | 'width' /* 其他30+属性 */>;
内容的提问来源于stack exchange,提问作者Daniel Kaplan
相关产品推荐
相关产品推荐

