TypeScript 命名空间与模块

TypeScript 中命名空间和模块的使用方式及区别

问题

TypeScript 中命名空间与模块有什么区别?分别如何使用?

解答

模块

TypeScript 与 ES2015 一样,任何包含顶级 importexport 的文件都被视为模块。不带有顶级导入导出声明的文件,其内容被视为全局可见。

例如,在 1.ts 中声明变量:

const a = 1

在另一个文件中再次声明同名变量会报错,因为它们都在全局空间中。

通过 export 引入模块系统可以解决这个问题:

const a = 10;

export default a

导出变量或类型:

export const a = 1
export type Person = {
    name: string
}

导入模块:

import { a, Person } from './export';

命名空间

命名空间用于解决重名问题,将相关的全局变量组织到一个对象中。使用 namespace 关键字定义:

namespace SomeNameSpaceName {
   export interface ISomeInterfaceName { }
   export class SomeClassName { }
}

需要在外部访问的类和接口必须添加 export 关键字。

使用方式:

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 = {}));

关键点

  • 模块通过 import/export 声明依赖关系,命名空间是全局对象,难以识别组件依赖
  • 命名空间会造成全局命名空间污染,在大型应用中不推荐使用
  • 正常项目开发建议使用模块,命名空间主要用于编写 .d.ts 类型声明文件
  • 模块中的变量默认私有,命名空间需要显式 export 才能外部访问