为什么 ES2015 模块语法优于自定义 TypeScript 命名空间?

cbd*_*per 7 namespaces module typescript typescript-typings .d.ts

来自typescript-eslint 文档

自定义 TypeScript 模块 ( module foo {}) 和命名空间 ( namespace foo {}) 被认为是过时的组织 TypeScript 代码的方式。现在首选 ES2015 模块语法 ( import/ export)。

来自 Typescripts文档

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

模块还依赖于模块加载器(例如 CommonJs/Require.js)或支持 ES 模块的运行时。模块提供更好的代码重用、更强的隔离和更好的捆绑工具支持。

还值得注意的是,对于 Node.js 应用程序,模块是默认设置,我们建议在现代代码中使用模块而不是命名空间。

我这个问题的目标是找出为什么模块语法优于命名空间。

到目前为止,这是我一直在做的事情:

PROJECT_TYPES.d.ts

我有多个d.ts文件,其中声明了包含我在项目源文件中使用的类型的命名空间。

declare namespace MY_NAMESPACE {
  type FOO = "FOO"
}
Run Code Online (Sandbox Code Playgroud)

这样做,我可以在项目的任何源文件中执行以下操作:

一些文件.ts

const foo: MY_NAMESPACE.FOO =  "FOO";
Run Code Online (Sandbox Code Playgroud)

它无需任何import/即可工作export

笔记:

  • 我正在使用d.ts文件,因为这些文件不包含任何import/export代码。
  • 我使用declare namespace而不是仅仅namespace因为没有declare关键字我会收到@typescript-eslint/no-unused-vars警告。

考虑到这MY_NAMESPACE是一个独特的名称,这是否应该被视为一种不好的做法?在这种情况下,我有理由使用modulesover吗namespaces?我不应该使用d.ts文件吗?

我的意思是,Typescript 文档提到:

模块提供更好的代码重用、更强的隔离和更好的捆绑工具支持。

但我不认为遵循上面描述的模式会失去任何这些好处,因为我所有的“真实”实际编译结果代码都在模块中分开。但为什么我的类型应该只在模块中?

Pet*_*man 5

的目的namespace是提供构造的逻辑分组,但是 ES2015 模块的引入允许我们使用文件系统来实现这一点,而不会污染全局范围。

它还为我们使用类型提供了更大的灵活性,我们可以使用目录推断命名空间。

例子

ES2015 之前

// src/geometry/types.d.ts
declare namespace Geometry{
    export type Shape = 'circle' | 'square'
}

// src/geometry/main.ts
let myShape: Geometry.Shape = 'square'
Run Code Online (Sandbox Code Playgroud)

ES2015 后

请注意,main.js我们没有使用Geometry前缀,这是有道理的,因为我们已经在geometry目录中

// src/geometry/types.ts
export type Shape = 'circle' | 'square'

// src/geometry/main.ts
import { Shape } from './types'
let myShape: Shape = 'square'

//src/geometry/index.ts
export * from './types'
export * from './main'

//src/index.ts
export * as Geometry from './geometry'
Run Code Online (Sandbox Code Playgroud)

参考