命名空间 vs 模块 vs 打字稿中的类型? [英] Namespaces vs modules vs typings in typescript?

查看:22
本文介绍了命名空间 vs 模块 vs 打字稿中的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

TL;DR

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

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

DefinitelyTyped 托管不同包的声明文件.名为 foo-bar 的绝对类型包的声明文件将在 npm 上发布为 @types/foo-bar.

命名空间

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

举个例子:

命名空间 foo {出口无功 x = 10;出口变量 y = 20;}

这个发射

var foo;(功能(富){foo.x = 10;foo.y = 20;})(foo || (foo = {}));

命名空间还有其他有用的属性,比如能够与函数、类或其他命名空间合并.但主要是,它们是在过渡时期引入的,在这个过渡时期,有必要为组织代码的两种主要方式提供服务:要么在全局范围内的众所周知的变量上提供 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;出口变量 y = 20;

转换为以下 CommonJS 模块:

"使用严格";Object.defineProperty(module.exports, "__esModule", { value: true });模块.exports.x = 10;module.exports.y = 20;

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

打字/类型

@types 成为获取声明文件的规定方式之前,

Typings"是声明文件(.d.ts 文件)的包管理器(稍后会详细介绍))

因此,typings"也成为了声明文件的一种昵称.

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

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

声明文件

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

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

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

将由以下声明描述:

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

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

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

绝对类型

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

您可以在 GitHub 上查看这里的存储库.

@types 和 npm

这是您如何从绝对类型中获取声明文件的方法.例如,如果你想要 lodash 的 .d.ts 文件,你可以写

npm install @types/lodash

这些有什么关系?

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

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

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

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

我还是不明白

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

Can someone please explain the difference between these concepts with an example,I'm really confused,what's the use of having three of them when they all serve the same purpose?

解决方案

TL;DR

Modules and namespaces are two means of encapsulation - breaking your code into parts that make sense. New code should be written with modules, rather than namespaces.

Declaration files ("typings") are used to describe modules, namespaces, variables, type declarations, etc. without actually containing any runnable code. Declaration files just tell TypeScript about what things exist, and how you can use those things.

DefinitelyTyped hosts declaration files for different packages. Declaration files for a DefinitelyTyped package called foo-bar will be published as @types/foo-bar on npm.

Namespaces

These formalized a somewhat dated pattern in JavaScript. The pattern was basically wrapping code in an IIFE to prevent conflicts of declarations in the global scope. These things tacked "exports" onto an object and assigned them to a variable that (hopefully) had unique name in the global scope, like $ or _ or whatever.

As an example:

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

This emits

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

Namespaces have other useful properties, like being able to merge with functions, classes, or other namespaces. But mainly, they were introduced during a transitionary period where it was necessary to serve both major ways to organize code: either providing the API surface on a well-known variable in the global scope (e.g. $, _, angular) or...

Modules

These all at once describe ECMAScript (standard JavaScript), CommonJS (i.e. Node.js), AMD (i.e. Require.js), and System.js modules. The crux of the idea here is that instead of just plopping variables into the global scope and hoping they don't conflict, each file gets its own unique scope and has exports.

In practice, the original implementations of modules (CommonJS, AMD, System.js) work the same way: wrap your code in a function to get the correct scope, and tack properties onto an object.

But TypeScript allows you to write code as if you were authoring ECMAScript modules with top-level export statements. Basically, to TypeScript, any file with top-level imports or exports is a module.

As an example, the following

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

translates to the following CommonJS module:

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

While namespaces have some useful use-cases, modules have become the clear way forward for breaking your code up into different pieces.

Typings/Types

"Typings" was a package manager for declaration files (.d.ts files) before @types became the prescribed way to get declaration files (more on this soon)

As a result, "typings" has also become a sort of nickname for declaration files.

If you are starting a new project, do not use Typings. The TypeScript ecosystem has largely standardized on using npm for declaration files. Additionally, because of the confusion in terminology, you should probably not call declaration files "typings".

With that said, we can move into the following topic:

Declaration files

Declaration files (.d.ts files, also called definition files) are TypeScript files that describe existing code. They can be produced from .ts files using the --declaration flag, or they can be authored manually to describe existing JavaScript code.

Declaration files contain declarations of the code that they actually describe. To be more specific, the following TypeScript function:

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

would be described by the following declaration:

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

If the original declaration was written in JavaScript, it could still be described using a declaration with explicit types like above.

This is important because the vast majority of JavaScript code isn't originally authored in TypeScript. So the community has come together and created a repository of declaration files called DefinitelyTyped.

DefinitelyTyped

This is a big git repository that describes over 3000 libraries at the time of this writing. Users can send pull requests for fixes and new packages.

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

@types and npm

This is how you can get declaration files from DefinitelyTyped. For example, if you wanted the .d.ts files for lodash, you could write

npm install @types/lodash

See

How do these relate?

Unfortunately the ideas here are subtle. Declaration files can describe everything in TypeScript. That means that they can describe what a module looks like, as well as what a namespace looks like.

So declaration files don't serve the same purpose as modules and namespaces. But they do describe to TypeScript when namespaces and modules exist, and how they can be used.

Basically, if you ever need to use something that looks like a module or a namespace and it was written in JS, you'll need a declaration file.

Even if it was written in TypeScript, if it was already compiled to .js, then you'll need a respective .d.ts file to use it.

I still don't understand

Hopefully this helped explain, but if not, check out

这篇关于命名空间 vs 模块 vs 打字稿中的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆