【问题标题】:Namespaces vs modules vs typings in typescript?命名空间与模块与打字稿中的打字?
【发布时间】:2017-11-13 13:44:11
【问题描述】:

谁能用一个例子解释一下这些概念之间的区别,我真的很困惑,当它们都用于同一目的时,三个它们有什么用?

【问题讨论】:

标签: typescript


【解决方案1】:

TL;DR

模块和命名空间是封装的两种方式——将代码分解成有意义的部分。新代码应该使用模块而不是命名空间来编写。

声明文件(“类型”)用于描述模块、命名空间、变量、类型声明等,但实际上并不包含任何可运行的代码。声明文件只是告诉 TypeScript 存在哪些东西,以及如何使用这些东西。

不同包的明确类型主机声明文件。名为foo-bar 的DefinitelyTyped 包的声明文件将在npm 上发布为@types/foo-bar

命名空间

这些形式化了 JavaScript 中有些过时的模式。该模式基本上是将代码包装在 IIFE 中,以防止全局范围内的声明冲突。这些东西将“导出”附加到一个对象上,并将它们分配给一个(希望)在全局范围内具有唯一名称的变量,例如 $_ 或其他。

举个例子:

namespace foo {
    export var x = 10;
    export var y = 20;
}

这会发出

var foo;
(function (foo) {
    foo.x = 10;
    foo.y = 20;
})(foo || (foo = {}));

命名空间还有其他有用的属性,例如能够与函数、类或其他命名空间合并。但主要是,它们是在过渡时期引入的,在这个过渡时期,有必要为组织代码的两种主要方式提供服务:要么在全局范围内的知名变量上提供 API 表面(例如 $_、@987654337 @) 或...

模块

这些都同时描述了 ECMAScript(标准 JavaScript)、CommonJS(即 Node.js)、AMD(即 Require.js)和 System.js 模块。这里想法的关键在于,不是将变量放入全局范围并希望它们不会发生冲突,而是每个文件都有自己独特的范围并具有导出。

在实践中,模块的原始实现(CommonJS、AMD、System.js)的工作方式相同:将您的代码包装在一个函数中以获得正确的范围,并将属性附加到一个对象上。

但是 TypeScript 允许您编写代码,就像您使用顶级 export 语句编写 ECMAScript 模块一样。基本上,对于 TypeScript,任何具有顶级 imports 或 exports 的文件都是一个模块。

作为一个例子,如下

export var x = 10;
export var y = 20;

转换为以下 CommonJS 模块:

"use strict";
Object.defineProperty(module.exports, "__esModule", { value: true });
module.exports.x = 10;
module.exports.y = 20;

虽然命名空间有一些有用的用例,但模块已成为将代码分解成不同部分的明确方法。

类型/类型

@types 成为获取声明文件的规定方式之前,“Typings”是声明文件(.d.ts 文件)的包管理器(稍后会详细介绍)

​​>

因此,“打字”也成为了声明文件的一种昵称。

如果您要开始一个新项目,不要使用打字。 TypeScript 生态系统在很大程度上标准化了将 npm 用于声明文件。 此外,由于术语混淆,您可能不应该将声明文件称为“类型”。

话虽如此,我们可以进入以下主题:

声明文件

声明文件(.d.ts 文件,也称为定义文件)是描述现有代码的 TypeScript 文件。它们可以使用--declaration 标志从.ts 文件生成,也可以手动编写以描述现有的JavaScript 代码。

声明文件包含它们实际描述的代码的声明。更具体地说,以下 TypeScript 函数:

function foo(x: number, y: number) {
    return x * 100 + y;
}

将由以下声明描述:

declare function foo(x: number, y: number): number

如果原始声明是用 JavaScript 编写的,它仍然可以使用具有上述显式类型的声明来描述。

这很重要,因为绝大多数 JavaScript 代码最初并不是用 TypeScript 编写的。所以社区已经走到一起,创建了一个声明文件的存储库,称为DefiniteTyped。

明确类型

这是一个大型 git 存储库,在撰写本文时描述了 3000 多个库。用户可以发送拉取请求以获取修复和新包。

You can take a look at the repo here on GitHub.

@types 和 npm

这就是您可以从DefinitelyTyped 获取声明文件的方式。例如,如果你想要 lodash 的 .d.ts 文件,你可以写

npm install @types/lodash

这些有什么关系?

不幸的是,这里的想法很微妙。声明文件可以描述 TypeScript 中的所有内容。这意味着他们可以描述模块的外观以及命名空间的外观。

因此声明文件的用途与模块和命名空间不同。但它们确实向 TypeScript 描述了命名空间和模块何时存在,以及如何使用它们。

基本上,如果您需要使用看起来像模块或命名空间的东西并且它是用 JS 编写的,那么您将需要一个声明文件。

即使它是用 TypeScript 编写的,如果它已经编译为 .js,那么您将需要一个相应的 .d.ts 文件来使用它。

我还是不明白

希望这有助于解释,但如果没有,请查看

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-04
    • 2014-01-19
    • 2019-10-13
    • 2017-02-11
    相关资源
    最近更新 更多