看来import x = require('x')
在es6中是无效的语法,并且打字稿文档中没有明确的解释。
答案 0 :(得分:3)
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标准。我建议阅读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模块的本机版本时,您将无法以这种方式导入函数或类。
答案 1 :(得分:1)
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
文件。这两个文件都将编译为将在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
的{{1}}属性设置为tsconfig.json
或使用true
标志。
--allowJs
在此示例中,// src/a.ts
import x from './x';
console.log( x() ); // === error ===
console.log( x.custom() ); // === error ===
语法指出import x
是默认导出,但是,x
没有默认导出,因为该功能缺少CommonJS模块系统。您可以通过将x.js
中的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
。但是,TypeScript可以将x.custom
插入module.exports
中,因此该程序可以正常工作。但是根据ECMAScript规范,x
不可调用或不可构造(使用x
)。所以这在语义上是不正确的。
TypeScript提供new
和import = require()
语法来处理这种情况。此语法仅限于TypeScript,并且仅在export =
中将module
属性设置为CommonJS
时才能使用。
tsconfig.json
语法表示将从模块中导出的单个对象。默认情况下,导出为export =
形式的JavaScript模块会自动获得module.exports
类型。
但是您可以在TypeScript或JavaScript文件中使用
export =
语法。 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()
语法,因为我们可以将其与CommonJS模块紧密关联,而且我们可以使用相同的语法将代码编译到import x from
和ECMAScript
模块系统中。通过在CommonJS
文件中将esModuleInterop
选项设置为true
,TypeScript编译器会在已编译的JavaScript代码中发出适当的帮助函数,以将默认导出功能添加到CommonJS模块。