打字稿中的命名空间和模块混淆?

打字稿的官方网站让我问一个问题,

“我们是否需要使用命名空间?”.

以下引用很好地解释了两件事:

It’s important to note that in TypeScript 1.5, the nomenclature has
changed. “Internal modules” are now “namespaces”. “External modules”
are now simply “modules”, as to align with ECMAScript 2015’s
terminology, (namely that module X { is equivalent to the
now-preferred namespace X {).

因此,他们建议TS团队更喜欢命名空间.
此外,它说我们应该使用“命名空间”来构建内部模块:

This post outlines the various ways to organize your code using
namespaces (previously “internal modules”) in TypeScript. As we
alluded in our note about terminology, “internal modules” are now
referred to as “namespaces”. Additionally, anywhere the module keyword
was used when declaring an internal module, the namespace keyword can
and should be used instead. This avoids confusing new users by
overloading them with similarly named terms.

以上引用全部来自Namespace部分,是的,它再次说明,但是在内部secnario中.
但在模块部分,有一段说:

Starting with ECMAScript 2015, modules are native part of the
language, and should be supported by all compliant engine
implementations. Thus, for new projects modules would be the
recommended code organization mechanism.

这是否意味着我不需要打扰命名空间,一直使用模块是建议的开发方式?

最佳答案

Does it mean that I don’t need to bother with namespace, use module all along is the suggested way to develop?

我不会这样说的……这是对发生的事情的另一种解释.有一次,在Typescript中使用了两个术语

>“外部模块” – 这是与JS社区称为AMD(例如RequireJS)或CommonJS(例如NodeJS)模块的TS模拟.这是可选的,对于一些只编写基于浏览器的代码的人来说,他们并不总是为此烦恼,特别是如果他们使用全局变量来跨文件进行通信.
>“内部模块” – 这是一种组织变量/函数的分层方式,因此并非所有内容都是全局的. JS中存在相同的模式,当人们将变量组织到对象/嵌套对象中而不是将它们全局化时.

随着Ecmascript 2015(a.k.a.ES6)的出现,它增加了属于“外部模块”类别的新的正式标准格式.由于这种变化,Typescript希望改变术语以匹配新的Javascript标准(因为它喜欢成为Javascript的超集,并尽力避免混淆来自Javascript的用户).因此,“外部模块”的切换被简化为“模块”,“内部模块”被重命名为“命名空间”.

你在这里找到的引用:

Starting with ECMAScript 2015, modules are native part of the language, and should be supported by all compliant engine implementations. Thus, for new projects modules would be the recommended code organization mechanism.

可能暗示对尚未使用(外部)模块的用户提供指导.至少考虑现在使用它.但是,对于ES6模块的支持仍然不完整,因为截至2016年5月,浏览器没有内置模块加载器.因此,您必须添加一个polyfill(在运行时处理它),如RequireJS或SystemJS,或者在构建时(在部署到您的网站之前)处理它的Bundler(如browserify或webpack).

那么,你会使用这两个模块(以前称为“外部模块”)和命名空间吗?绝对 – 我在代码库中经常使用它们.我使用(外部)模块来组织我的代码文件.

Typescript中的命名空间非常有用.具体来说,我使用名称空间声明合并作为一种类型安全的方式来为函数对象本身添加额外的属性(JS中经常使用的模式).此外,虽然名称空间与常规对象变量非常相似,但您可以从其名称中挂起子类型(嵌套接口,类,枚举等).

以下是具有属性的函数示例(在NodeJS库中非常常见):

function someUsefulFunction() {
  // asynchronous version
  return ...; // some promise
}

namespace someUsefulFunction {
  export function sync() {
    // synchronous version
  }
}

这允许消费者执行这种常见的NodeJS模式:

// asynchronous consumer
someUsefulFunction()
  .then(() => {
    // ... 
  });

// synchronous consumer
someUsefulFunction.sync();

同样地,假设您有一个接受选项对象的API.如果该选项类型特定于该API,

function myFunc(options?: myFunc.Options) {
    // ...
}

namespace myFunc {
    export interface Options {
        opt1?: number;
        opt2?: boolean;
        opt3?: string;
    }
}

在这种情况下,您不必使用选项的类型声明污染较大的命名空间(例如整个模块范围).

希望这可以帮助!

点赞