TypeScript 中的命名空间与模块
理解 TypeScript 命名空间和模块的概念及使用场景
问题
TypeScript 中命名空间(namespace)与模块(module)有什么区别?分别在什么场景下使用?
解答
模块
TypeScript 与 ES2015 一样,任何包含顶级 import 或 export 的文件都被视为一个模块。
如果文件不包含顶级的 import 或 export 声明,其内容会被视为全局可见。例如在 1.ts 中声明变量:
const a = 1
在另一个文件中再次声明同名变量会报错,因为它们都在全局作用域中。
通过 export 引入模块系统可以解决这个问题:
const a = 10;
export default a
模块可以导出变量、类型等:
export const a = 1
export type Person = {
name: string
}
通过 import 引入模块:
import { a, Person } from './export';
命名空间
命名空间用于解决命名冲突问题,将相关的全局变量组织到一个对象中。
使用 namespace 关键字定义,需要导出的成员要添加 export:
namespace SomeNameSpaceName {
export interface ISomeInterfaceName { }
export class SomeClassName { }
}
使用方式:
SomeNameSpaceName.SomeClassName
命名空间本质上是一个对象:
namespace Letter {
export let a = 1;
export let b = 2;
export let c = 3;
}
编译后的 JavaScript:
var Letter;
(function (Letter) {
Letter.a = 1;
Letter.b = 2;
Letter.c = 3;
})(Letter || (Letter = {}));
区别与使用建议
命名空间是全局命名空间下的一个普通 JavaScript 对象,在大型应用中难以识别组件间的依赖关系。
模块可以明确声明依赖关系,更适合现代 TypeScript 项目开发。
在实际开发中,推荐使用模块而非命名空间。命名空间主要用于编写 .d.ts 声明文件,为 JavaScript 库标记类型。
关键点
- 模块通过
import/export声明,具有独立作用域,可明确声明依赖关系 - 命名空间使用
namespace定义,本质是全局对象,用于组织相关变量 - 现代 TypeScript 项目推荐使用模块,命名空间主要用于类型声明文件
- 没有顶级
import/export的文件内容会被视为全局可见
目录