typescript 中 `import x = require('x')` 和 `const x = require('x')` 之间的区别
Posted
技术标签:
【中文标题】typescript 中 `import x = require(\'x\')` 和 `const x = require(\'x\')` 之间的区别【英文标题】:Difference between `import x = require('x')` and `const x = require('x')` in typescripttypescript 中 `import x = require('x')` 和 `const x = require('x')` 之间的区别 【发布时间】:2019-03-03 05:54:09 【问题描述】:似乎import x = require('x')
在es6中是无效语法,打字稿文档中也没有明确的解释。
【问题讨论】:
import
导入,const
定义一个常量变量....
import x from 'x'
和import x = require('x')
的区别如何?
Typescript import/as vs import/require?的可能重复
insights.untapt.com/webpack-import-require-and-you-3fd7f5ea93c0
【参考方案1】:
Q1:import … = require(…)
与 const … = require(…)
在运行时(或代码编译后),两种语法没有区别,第一种转换为第二种。
与import
:
import x = require('x')
此语法特定于 TypeScript。常量x
的类型由导入包或包@types/x
中定义的某些类型给出。
与const
:
const x = require('x')
这是 javascript 中的有效语法,当然在 TypeScript 中也是如此。在 TypeScript 中,常量 x
的类型为 any
。
Q2:import … from …
与 import … = require(…)
import x from 'x'
和import x = require('x')
的区别呢
import … from …
的语法来自 ES6 标准。我建议阅读 this introduction 到 ES6 模块以及如何导入和导出它们。
但是,简而言之,import x from 'x'
的语法等价于:
import x = require('x').default
(注意.default
成员。)
如何将import … = require(…)
转换为 ES6 语法
ES6 标准规定所有导出的成员都可以导入单个“命名空间对象模块”。
那么import x = require('x')
最接近的标准语法是:
import * as x from 'x'
此语法目前适用于 TypeScript 转译,因为代码已转换为 const … = require(…)
。
但是:此语法只能在标准定义的上下文中使用。因为,当您的代码将使用原生版本的 ES6 模块时,您将无法以这种方式导入函数或类。
【讨论】:
【参考方案2】:require()
函数在 TypeScript 中不存在。 ECMAScript 的模块系统使用import
和export
关键字。 Node.js使用的CommonJS模块系统中存在require
、module.exports
和exports
关键字。
所以当你输入 const x = require('x')
时,TypeScript 会抱怨它不知道 require
是什么。您需要安装 @types/node
包来安装 CommonJS 模块系统的类型定义,以便从 TypeScript 中使用它。
├── src/
| ├── a.ts
| └── x.js
└── dist/
├── a.js
└── x.js
假设您有a.ts
和x.js
作为源文件。 a.ts
文件导入 x.js
文件。这两个文件都将编译为.js
将在 Node.js 上运行的文件。那么让我们来了解一下这些编译成 JavaScript 后的样子。
// dist/x.js
exports = module.exports = function() return 'MAIN';
exports.custom = function() return 'CUSTOM';
// dist/a.js
const x = require( 'x.js' );
console.log( x() ); // 'MAIN'
console.log( x.custom() ); // 'CUSTOM'
x.js
将exports
和module.exports
设置为调用时返回MAIN
的函数。由于函数在 JavaScript 中也是 object
,因此我们可以为其分配一些属性。 custom
属性是一个在调用时返回 CUSTOM
的函数。
// src/x.js
exports = module.exports = function() return 'MAIN';
exports.custom = function() return 'CUSTOM';
src/x.js
已经是一个具有 CommonJS 模块语法的 .js
文件。我们可以使用 import
语法将其导入到 TypeScript 文件中。我们需要在编译项目时将tsconfig.json
的allowJs
属性设置为true
或使用--allowJs
标志。
方法一
// src/a.ts
import x from './x';
console.log( x() ); // === error ===
console.log( x.custom() ); // === error ===
在此示例中,import x
语法指出 x
是 默认导出,但是,x.js
没有默认导出,因为 CommonJS 模块系统中缺少该功能。您可以通过将tsconfig.json
中的esModuleInterop
选项设置为true
来允许此操作。所以当你尝试编译这个程序时,你会得到如下的编译错误。
a.ts:1:8 - error TS1259: Module '"./x"' can only be default-imported using the 'esModuleInterop' flag
1 import x from './src/q';
~
src/q.js:1:11
1 exports = module.exports = function() return "MAIN";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This module is declared with using 'export =', and can only be used with a default import when using the 'esModuleInterop' flag.
方法二
// src/a.ts
import * as x from './x';
console.log( x() ); // `MAIN`
console.log( x.custom() ); // `CUSTOM`
在此示例中,import * as x
语法规定所有导出成员都将存储在x
对象 中。因此,x
本身并不代表任何东西,它只是一个包含所有导出的容器,例如x.custom
。但是,TypeScript 可以将 module.exports
与 x
交互,因此该程序可以正常工作。但根据 ECMAScript 规范,x
不应该是可调用或可构造的(使用 new
)。所以这在语义上是不正确的。
方法三
TypeScript 提供 import = require()
和 export =
语法来处理这种情况。此语法仅限于 TypeScript,并且只能在 tsconfig.json
中的 module
属性设置为 CommonJS
时使用。
export =
语法表示将从模块中导出的单个对象。默认情况下,以module.exports
形式导出的JavaScript 模块会自动获取export =
类型。
但您可以在 TypeScript 或 JavaScript 文件中使用
exports = function() ...
语法。 TypeScript 编译器会将此语法转换为已编译的 JavaScript 代码中的module.exports
语法。
// src/a.ts
import x = require( './x' );
console.log( x() ); // `MAIN`
console.log( x.custom() ); // `CUSTOM`
当模块具有exports =
类型时,使用import = require()
语法导入它的理想方式。
我个人更喜欢使用import x from
语法,因为我们可以将它与CommonJS 模块密切相关,而且我们使用相同的语法将代码编译为ECMAScript
和CommonJS
模块系统。通过在 tsconfig.json
文件中将 esModuleInterop
选项设置为 true
,TypeScript 编译器会在编译的 JavaScript 代码中发出适当的帮助函数,以将 默认导出 功能添加到 CommonJS 模块。
【讨论】:
以上是关于typescript 中 `import x = require('x')` 和 `const x = require('x')` 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章
将 Angular 1.x 与 TypeScript 1.5 和 SystemJS 一起使用
在 TypeScript 中使用 import/require 来获取接口声明
TypeScript 中的 Import 和 require 有啥不同?
TypeScript - import ... 和 import ... 之间的区别(带花括号)