TypeScript库中如何同时导出接口与具体类并实现接口调用
解决TypeScript接口导出为对象属性时的TS2693错误
问题原因
你遇到的TS2693错误本质是:TypeScript的接口是类型,仅存在于编译阶段,编译为JavaScript后会被完全擦除,无法像类(属于值)那样作为对象的属性导出。直接把接口放到导出对象里,TS会认为你在试图将一个不存在的“值”赋值给对象属性,因此报错。
解决方案
根据你希望使用者通过mylib.IFoo和mylib.Foo调用的需求,推荐以下两种可行方案:
方案1:导入整个模块作为命名空间(最简洁)
这种方式符合TypeScript模块化规范,无需额外声明:
- 在
src/index.ts中直接导出接口和类:
export interface IFoo { doSomething(): void; } export class Foo implements IFoo { doSomething() { // 你的实现逻辑 console.log('执行Foo的doSomething方法'); } }
- 在
test/Foo.spec.ts中导入整个模块并使用:
import * as mylib from '../src'; const foo: mylib.IFoo = new mylib.Foo(); foo.doSomething(); // 正常调用
方案2:通过声明合并实现对象+类型的导出
如果你必须将类封装在mylib对象中导出,同时保留接口的类型访问,可以用声明合并的方式:
- 在
src/index.ts中:
// 定义接口 export interface IFoo { doSomething(): void; } // 定义并实现类 export class Foo implements IFoo { doSomething() { console.log('执行Foo的doSomething方法'); } } // 创建包含类的导出对象 export const mylib = { Foo }; // 声明mylib的命名空间,让它包含IFoo类型 declare namespace mylib { export type IFoo = import('./index').IFoo; }
- 在
test/Foo.spec.ts中直接使用:
import { mylib } from '../src'; const foo: mylib.IFoo = new mylib.Foo(); foo.doSomething();
关键说明
- 类型(接口、类型别名等)和值(类、函数、变量等)在TypeScript中属于不同的空间,不能直接混在一起作为对象属性导出。
- 方案1是TypeScript官方推荐的模块化使用方式,代码更简洁易维护;方案2适合需要将类封装在特定对象下的场景。
内容的提问来源于stack exchange,提问作者Source
相关产品推荐
相关产品推荐

