命名空间vs模块与打字稿中的打字?

ven*_*usa 7 typescript

有人可以用一个例子来解释这些概念之间的区别,我真的很困惑,当它们都服务于同一目的时,有三个这样的用途是什么?

Dan*_*ser 23

TL; DR

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

声明文件("typings")用于描述模块,名称空间,变量,类型声明等,而不实际包含任何可运行的代码.声明文件只是告诉TypeScript有关存在的内容,以及如何使用这些内容.

DefinitelyTyped托管不同包的声明文件.被调用的DefinitelyTyped包的声明文件foo-bar@types/foo-bar在npm 上发布.

命名空间

这些在JavaScript中形式化了一种过时的模式.该模式基本上是将代码包装在IIFE中,以防止全局范围内的声明冲突.这些东西上涨"出口"到一个对象,并将其分配给一个变量在全球范围内是(希望)具有独特的名称,如$_或什么的.

举个例子:

namespace foo {
    export var x = 10;
    export var y = 20;
}
Run Code Online (Sandbox Code Playgroud)

这会发出

var foo;
(function (foo) {
    foo.x = 10;
    foo.y = 20;
})(foo || (foo = {}));
Run Code Online (Sandbox Code Playgroud)

命名空间具有其他有用的属性,例如能够与函数,类或其他命名空间合并.但主要是,它们是在一个转型期推出在有必要同时服务于主要的方式来组织代码:无论是在全球范围内提供的API表面上著名的变量(例如$,_,angular)或...

模块

这些都同时描述了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;
Run Code Online (Sandbox Code Playgroud)

转换为以下CommonJS模块:

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

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

分型/类型

"Typings"是声明文件(.d.ts文件)的包管理器,之后@types成为获取声明文件的规定方式(很快就会有更多内容)

结果,"typings"也成为声明文件的一种昵称.

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

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

声明文件

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

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

function foo(x: number, y: number) {
    return x * 100 + y;
}
Run Code Online (Sandbox Code Playgroud)

将通过以下声明来描述:

declare function foo(x: number, y: number): number
Run Code Online (Sandbox Code Playgroud)

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

这很重要,因为绝大多数JavaScript代码最初都不是在TypeScript中编写的.因此社区聚集在一起并创建了一个名为DefinitelyTyped的声明文件库.

DefinitelyTyped

这是一个很大的git存储库,在撰写本文时描述了超过3000个库.用户可以发送修复和新包的拉取请求.

您可以在GitHub上查看这里的回购.

@types 和npm

这是你如何从DefinitelyTyped获取声明文件.例如,如果你想要.d.tslodash 的文件,你可以写

npm install @types/lodash
Run Code Online (Sandbox Code Playgroud)

看到

这些如何相关?

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

因此,声明文件与模块和命名空间的用途不同.但是当命名空间和模块存在时,它们会对TypeScript进行描述,以及如何使用它们.

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

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

我还是不明白

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