You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在多文件中合并Function与Namespaces?

让TypeScript模块兼具函数调用与子方法访问能力

现有代码结构

我们的TypeScript代码按如下结构组织:

module/
├── module.a.ts
├── module.b.ts
├── module.c.ts
├── module.barrel.ts
└── index.ts

子模块示例(以module.a.ts为例)

每个子模块导出一个功能函数:

// module.a.ts
export function a() {
  console.log('from A');
}

module.b.ts和module.c.ts结构类似,分别导出b()和c()函数,输出对应内容。

barrel文件(module.barrel.ts)

通过barrel文件统一导出所有子模块:

export * from './module.a.ts';
export * from './module.b.ts';
export * from './module.c.ts';

入口文件(原index.ts)

将barrel的导出内容作为命名空间导出:

export * as MyModule from './module.barrel';

当前用法

现在可以导入命名空间并调用子方法:

import { MyModule } from './module';

MyModule.a();
MyModule.b();
MyModule.c();

需求实现

我们需要修改index.ts,让MyModule既能作为函数直接调用(输出from ROOT MODULE),又能保留原有子方法的访问能力,支持如下用法:

import { MyModule } from './module';

MyModule(); // 输出 'from ROOT MODULE'
MyModule.a(); // 输出 'from A'
MyModule.b(); // 输出 'from B'
MyModule.c(); // 输出 'from C'

修改后的index.ts代码

// 导入所有子模块的导出内容
import * as ModuleExports from './module.barrel';

// 定义根模块的函数逻辑,并合并类型
const MyModule = (() => {
  console.log('from ROOT MODULE');
}) as typeof ModuleExports & (() => void);

// 将子模块的方法挂载到函数对象上
Object.assign(MyModule, ModuleExports);

// 导出最终的模块
export { MyModule };

原理说明

  1. 函数对象挂载属性:JavaScript中函数本质是对象,因此可以通过Object.assign将子模块的方法挂载到MyModule函数上。
  2. 类型合并:通过交叉类型typeof ModuleExports & (() => void),让TypeScript识别MyModule既是一个可调用的函数,又拥有子模块的所有方法类型,避免类型报错。

内容的提问来源于stack exchange,提问作者mikoloism

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 10:08:20