import … = require(…)
与 const … = require(…)
在运行时(或代码编译后),两种语法之间没有区别,第一个语法转换为第二个语法。
import
:import x = require('x')
此语法特定于 TypeScript。常量
x
的类型由导入包或包 @types/x
中定义的某些类型给出。
const
:const x = require('x')
这是 JavaScript 中的有效语法,当然也是 TypeScript 中的有效语法。在 TypeScript 中,常量
x
的类型为 any
。
import … from …
与 import … = require(…)
和import x from 'x'
之间有什么区别?import x = require('x')
语法
import … from …
来自ES6标准。我建议阅读这篇关于 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 模块的本机版本时,您将无法以这种方式导入函数或类。
TypeScript 中不存在
require()
函数。 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
文件。这两个文件都将被编译为将在 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 文件中。我们需要将 allowJs
的 tsconfig.json
属性设置为 true
或在编译项目时使用 --allowJs
标志。
// src/a.ts
import x from './x';
console.log( x() ); // === error ===
console.log( x.custom() ); // === error ===
在此示例中,
import x
语法指出x
是默认导出,但是,x.js
没有默认导出,因为 CommonJS 模块系统中缺少该功能。您可以通过将 esModuleInterop
中的 true
选项设置为 tsconfig.json
来允许此操作。因此,当您尝试编译此程序时,您将收到以下编译错误。
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,并且仅当 module
中的 CommonJS
属性设置为 tsconfig.json
时才能使用。
export =
语法表示将从模块导出的单个对象。默认情况下,以 module.exports
形式导出的 JavaScript 模块会自动获取 export =
类型。
但是您可以在 TypeScript 或 JavaScript 文件中使用
语法。 TypeScript 编译器会在编译后的 JavaScript 代码中将此语法转换为exports = function(){ ... }
语法。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
模块系统。通过在 esModuleInterop
文件中将 true
选项设置为 tsconfig.json
,TypeScript 编译器会在编译后的 JavaScript 代码中发出适当的辅助函数,以将 default export 功能添加到 CommonJS 模块。