【发布时间】:2017-11-13 13:44:11
【问题描述】:
谁能用一个例子解释一下这些概念之间的区别,我真的很困惑,当它们都用于同一目的时,三个它们有什么用?
【问题讨论】:
-
关于命名空间和模块,请参阅:stackoverflow.com/a/30357635/6680611
标签: typescript
谁能用一个例子解释一下这些概念之间的区别,我真的很困惑,当它们都用于同一目的时,三个它们有什么用?
【问题讨论】:
标签: typescript
模块和命名空间是封装的两种方式——将代码分解成有意义的部分。新代码应该使用模块而不是命名空间来编写。
声明文件(“类型”)用于描述模块、命名空间、变量、类型声明等,但实际上并不包含任何可运行的代码。声明文件只是告诉 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 文件来使用它。
希望这有助于解释,但如果没有,请查看
【讨论】: