TypeScript 变量与导入

TypeScript var vs import

在TypeScript中,

有什么区别
 import http = require('http');

 var http = require('http');

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

您的 import 语句是 TypeScript,不会 运行 在 Node 中。您需要先将其编译(转译?)为 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 是你可以 compare/contrast 用 require 但不是真的 var.

我也有同样的疑问。刚在 Typescript 的 "Alias" 部分找到这个:

This is similar to using var, but also works on the type and namespace meanings of the imported symbol. Importantly, for values, import is a distinct reference from the original symbol, so changes to an aliased var will not be reflected in the original variable

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

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

模块 CommonJs/Node

@mfc: This is the case that corresponds to your question.

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 将节点类型添加到项目中(请参阅此).

ES6 模块

@mfc: This is not the case you've asked for. But it's in so I've taken it into account.

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

  • "Full" 命名导出的导入:import * as lib from 'lib';
  • "Picking" 命名导出的导入:import { square, diag } from 'lib';
  • 导入默认导出:import myFunc from 'myFunc';

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

  • ES6 → 无变化
  • CommonJSvar ... = require('...');
  • AMDdefine(...);

命名空间

别名

@mfc: This is not the case you've asked for. But it's in so I've added here to have the full picture.

namespace, formerly called "(internal) module", import is used to create an 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;,cf. TypeScript PlayGround.

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

全局模块

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

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

TypeScript 支持此 kind of imports. The compiler will try to fetch the corresponding typing definition to understand the library effects, for instance the new method Reflect.getMetadata()