Modules

模块可以包含代码和声明。

Namespaces

命名空间是组织代码的一种特定于类型的方式。
命名空间是全局名称空间中命名的JavaScript对象。这使得命名空间的使用非常简单。与模块不同,它们可以跨多个文件。
就像所有全局名称空间污染一样,很难识别组件依赖关系,尤其是在大型应用程序中。

缺陷

一个常见的错误是试图使用/// 语法引用模块文件,而不是使用import语句。要理解这种区别,我们首先需要理解编译器如何根据导入的路径定位模块的类型信息的道路。
编译器将尝试查找 .ts、.tsx 和 .d.ts 与适当的路径。如果找不到特定的文件,则编译器将查找环境模块声明。回忆一下,这些需要在 .d 中声明。

  1. // myModules.d.ts
  2. declare module "SomeModule" {
  3. export function fn(): string;
  4. }
// myOtherModule.ts
/// <reference path="myModules.d.ts" />
import * as m from "SomeModule";
m.fn()

这里的引用标记允许我们找到包含环境模块声明的声明文件。这就是node.d.ts的引用方式。

错误的引用方式

如果你把一个程序从命名空间转换成模块,很容易得到这样的文件:

// Shapes.d.ts
export namespace Shapes {
  export class Triangle {
    /* ... */
  }
  export class Square {
    /* ... */
  }
}

这里的顶级模块将 Triangle 和 Square 无缘无故地包裹起来。这让模块的使用者感到困惑和烦恼。

mport * as shapes from "./shapes";
let t = new shapes.Shapes.Triangle(); // shapes.Shapes?

为了重申不应该尝试命名模块内容的原因,命名空间的一般思想是提供结构的逻辑分组并防止名称冲突。因为模块文件本身已经是一个逻辑分组,并且它的顶级名称是由导入它的代码定义的,所以没有必要为导出的对象使用额外的模块层。

// shapes.ts
export class Triangle {
/* ... */
}
export class Square {
/* ... */
}
import * as shapes from "./shapes";
let t = new shapes.Triangle();