TypeScript var 与导入

Posted

技术标签:

【中文标题】TypeScript var 与导入【英文标题】:TypeScript var vs import 【发布时间】:2015-07-03 18:45:23 【问题描述】:

在TypeScript中,有什么区别

 import http = require('http');

 var http = require('http');

我看到这两种方式都在代码源中使用,它们可以互换吗?

【问题讨论】:

第一个对我来说无效? 你的意思是import http from 'http' 可能吗?前者是 ES6 模块导入声明,后者是 CommonJS 模块导入。 @adeneo,第一个是由 Visual Studio 使用他们的 Typescript + node.js 插件自动生成的 好的,但这仍然不是 javascript,可能是 Typescript。在 javascript 中,就像 Felix 上面写的那样,要么是 ES6 import stuff from module,要么是 Node 中使用的 commonJS 版本,带有一个常规变量和对 require()的调用 【参考方案1】:

您的 import 语句是 TypeScript,不会在 Node.js 中按原样运行。您需要先将其编译(转译?)为 JavaScript。您可以阅读 TypeScript 文档以了解有关 TypeScript import 关键字如何工作的更多信息。请参阅"Using Modules" subsection of the "Namespaces and Modules" section of the TypeScript handbook。

在 JavaScript 中也有一个 import 关键字,但它不像 TypeScript 的 import 那样工作。它仅适用于支持 ES6 模块的 Node 版本。 importrequire 之间存在差异,您可以在 "ES6 Modules: The Final Syntax" 阅读。 import 是您可以与 require 比较/对比的东西,但不是真正的 var

【讨论】:

这如何回答这个问题?信息很有趣,但不是答案。 @viscanner 该问题随后被编辑以添加“TypeScript”(原始问题中没有)。然后 在发布此答案 8 个月后,再次对其进行编辑以删除“Node.js”,从而使此答案出现无效。此答案解决了撰写此答案时出现的问题。 @Trott,MS 已删除您提供的名为“Going External”的链接。我翻阅了他们的新 github 文档,但找不到该页面。您是否有机会找到它并在您的答案中而不是链接中快速了解它? @bgura TypeScript 和 Node.js 发生了很大变化,但相关部分已重命名为“使用模块”,可以在 typescriptlang.org/docs/handbook/… 找到。我会更新答案。【参考方案2】:

我也有同样的询问。刚刚在 Typescript 的“别名”部分找到了这个:

这类似于使用 var,但也适用于导入符号的类型和命名空间含义。重要的是,对于值,导入是与原始符号不同的引用,因此对别名变量的更改不会反映在原始变量中

https://www.typescriptlang.org/docs/handbook/namespaces.html#aliases

【讨论】:

这是主要区别。如果我们使用 var ,它似乎是通过引用传递的。在英语中,这意味着(根据我的理解,如果我错了,请纠正我)你分配给 var 的对象发生的任何更改,即使你没有重新分配它也会改变。而使用 import 将创建它的独立副本。【参考方案3】:

TypeScript import 关键字有多种用法,其中一些取决于环境,解释了为什么它会令人困惑。让我们看看最小细节级别(因为在实际项目中它可能更复杂):

模块 CommonJs / 节点

@mfc:这与您的问题相对应。

TypeScript 项目使用 CommonJs 模块,通常是节点项目:

// tsconfig.json

    "compilerOptions": 
        "module": "commonjs",
        ...
    

在这种情况下,import _ = require('http');版本#1)被转换为var _ = require('http');版本#2)。所以版本 #1 是 TypeScript 语法,而版本 #2 是 JavaScript 语法。

require() 在版本 1 中受支持,但在版本 #2 中不支持(错误[ts] Cannot find name 'require'.),除非通过npm i @types/node --save-dev 将节点类型添加到项目中(请参阅此*** Q/A)

模块 ES6

@mfc:这不是你要求的情况。但它在Trott's answer 中,所以我已将其考虑在内。

import 是 ES6 关键字并且有它的 own syntax:

命名导出的“完全”导入:import * as lib from 'lib'; 命名导出的“选择”导入:import square, diag from 'lib'; 默认导出的导入:import myFunc from 'myFunc';

根据上面提到的模块编译器选项,这些导入的转译方式不同:

ES6 → 没有变化 CommonJSvar ... = require('...'); AMDdefine(...);

命名空间

别名

@mfc:这不是你要求的情况。但它在Jose A's answer,所以我在这里添加了完整的图片。

在以前称为“(内部)模块”的namespace 中,import 用于创建alias,这是另一个命名空间的导出元素的快捷方式。

namespace Root.Branch.Leaf 
    export const configPath = '...';


namespace LeafClient 
    import configPath = Root.Branch.Leaf.configPath;
    console.log(`configPath=$configPath`);

import configPath = Root.Branch.Leaf.configPath; 行被转换成var configPath = Root.Branch.Leaf.configPath;,参见。 TypeScript PlayGround.

注意命名空间之外的用法,因为它创建了全局变量!

全局模块

有些库会修改全局对象(浏览器中的window全局变量),例如:

jQuery 及其$ 全局变量, reflect-metadata 扩展为 Reflect

ES6 语法还允许使用 side effects only import 加载此类库:import "reflect-metadata";

TypeScript 支持这个kind of imports。编译器将尝试获取相应的typing definition 以了解库效果,例如新方法Reflect.getMetadata()

【讨论】:

以上是关于TypeScript var 与导入的主要内容,如果未能解决你的问题,请参考以下文章

用于导入类型的 Eslint typescript no-unused-vars 触发器

要求语句不是导入语句的一部分。eslint@typescript-eslint/no-var-需要从存储中导入打字稿

TypeScript入门学习之路

Chutzpah - 使用 jasmine 和 TypeScript 进行 AngularJS 测试

如何使用 sequelize-typescript 从单个字段中引用多个模型?

TypeScript `infer` 关键字