有人可以通过一个例子来解释这些概念之间的区别,我真的很困惑,当它们都服务于同一目的时,使用其中三个是什么?
答案 0 :(得分:21)
模块和命名空间是两种封装方式 - 将代码分解为有意义的部分。新代码应该用模块而不是命名空间编写。
声明文件(" typings")用于描述模块,命名空间,变量,类型声明等,而不实际包含任何可运行的代码。声明文件只是告诉TypeScript存在的内容,以及如何使用这些内容。
针对不同包的DefinitelyTyped主机声明文件。名为foo-bar
的DefinitelyTyped包的声明文件将在npm上发布为@types/foo-bar
。
这些在JavaScript中形式化了一种过时的模式。该模式基本上是将代码包装在IIFE中,以防止全局范围内的声明冲突。这些东西加上了'#34;出口"在一个对象上并将它们分配给一个变量(希望)在全局范围内具有唯一的名称,如$
或_
或其他。
举个例子:
namespace foo {
export var x = 10;
export var y = 20;
}
这会发出
var foo;
(function (foo) {
foo.x = 10;
foo.y = 20;
})(foo || (foo = {}));
命名空间具有其他有用的属性,例如能够与函数,类或其他命名空间合并。但主要是,它们是在过渡时期引入的,在此期间必须提供组织代码的两种主要方式:在全局范围内的一个众所周知的变量上提供API表面(例如$
,{{1} },_
)或...
这些一下子描述了ECMAScript(标准JavaScript),CommonJS(即Node.js),AMD(即Require.js)和System.js模块。这个想法的关键在于,不是仅仅将变量放入全局范围并希望它们不会发生冲突,而是每个文件都有自己独特的范围并且具有导出。
实际上,模块的原始实现(CommonJS,AMD,System.js)的工作方式相同:将代码包装在函数中以获取正确的范围,并将属性粘贴到对象上。
但TypeScript允许您编写代码,就好像您使用顶级angular
语句编写ECMAScript模块一样。基本上,对于TypeScript,任何顶级export
或import
s的文件都是模块。
例如,以下
export
转换为以下CommonJS模块:
export var x = 10;
export var y = 20;
虽然命名空间有一些有用的用例,但模块已经成为将代码分解成不同部分的明确方法。
"分型"是"use strict";
Object.defineProperty(module.exports, "__esModule", { value: true });
module.exports.x = 10;
module.exports.y = 20;
成为获取声明文件的规定方式之前的声明文件(.d.ts
文件)的包管理器(很快就会有更多内容)
结果,"打字"也已成为声明文件的昵称。
如果您要开始新项目,请勿使用“打字”。 TypeScript生态系统在很大程度上标准化了将npm用于声明文件。 此外,由于术语混淆,您可能不应该调用声明文件" typings"。
话虽如此,我们可以进入以下主题:
声明文件(@types
文件,也称为定义文件)是描述现有代码的TypeScript文件。可以使用.d.ts
标志从.ts
文件生成它们,也可以手动创建它们来描述现有的JavaScript代码。
声明文件包含它们实际描述的代码的声明。更具体地说,是以下TypeScript函数:
--declaration
将通过以下声明来描述:
function foo(x: number, y: number) {
return x * 100 + y;
}
如果原始声明是用JavaScript编写的,那么仍然可以使用带有上述显式类型的声明来描述它。
这很重要,因为绝大多数JavaScript代码最初都是在TypeScript中编写的。因此社区聚集在一起并创建了一个名为DefinitelyTyped的声明文件存储库。
这是一个很大的git存储库,在撰写本文时描述了超过3000个库。用户可以发送修复和新包的拉取请求。
You can take a look at the repo here on GitHub
declare function foo(x: number, y: number): number
和npm 这是你如何从DefinitelyTyped获取声明文件。例如,如果你想要lodash的@types
文件,你可以写
.d.ts
见
不幸的是,这里的想法很微妙。声明文件可以描述TypeScript中的所有内容。这意味着他们可以描述模块的外观,以及命名空间的外观。
因此,声明文件与模块和命名空间的用途不同。但是当名称空间和模块存在时,它们会向TypeScript描述,以及如何使用它们。
基本上,如果您需要使用看起来像模块或命名空间的东西而且它是用JS编写的,那么您需要一个声明文件。
即使它是用TypeScript编写的,如果它已编译为npm install @types/lodash
,那么您需要一个相应的.js
文件才能使用它。
希望这有助于解释,但如果没有,请查看