打字稿中的import x = require('x')`和`const x = require('x')`之间的区别

时间:2018-09-27 10:28:34

标签: typescript ecmascript-6

看来import x = require('x')在es6中是无效的语法,并且打字稿文档中没有明确的解释。

2 个答案:

答案 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的模块系统使用importexport关键字。 Node.js使用的CommonJS模块系统中存在requiremodule.exportsexports关键字。

因此,当您键入const x = require('x')时,TypeScript会抱怨它不知道require是什么。您需要安装@types/node软件包才能为CommonJS模块系统安装类型定义,以便从TypeScript中使用它。

├── src/
|   ├── a.ts
|   └── x.js
└── dist/
    ├── a.js
    └── x.js

假设您有a.tsx.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.jsexportsmodule.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提供newimport = 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 fromECMAScript模块系统中。通过在CommonJS文件中将esModuleInterop选项设置为true,TypeScript编译器会在已编译的JavaScript代码中发出适当的帮助函数,以将默认导出功能添加到CommonJS模块。