TypeScript 中的多种 import 解义

JavaScript 中有多种 export 的方式,而 TypeScript 中针对这种情况做了多种 import 语法,最常见的就是 import * as path from 'path' 这种。这篇文章主要来讲解 TypeScript 中不同的 import 具有什么意义。

原文首发于我的个人网站:听说 - https://tasaid.com,推荐在我的网站阅读更多技术文章。

前端开发 QQ 群:377786580

从 export 说起

有很多朋友都问过我关于 TypeScript 中不同 import 的含义,最典型的就是下面的 import 语法:

import * as path from 'path'

不少人疑问这句代码究竟是什么意思,这里我们要先从 js 的 export 开始说。

首先,JavaScript 的模块化方案,在历史的演进中,有多种导出模块的方式:exportsmodule.exportsexportexport default

在 nodejs 中内置的模块遵循的都是 CommonJS 规范,语法为 module.exports 和 exports

// 模块中的 exports 变量指向 module.exports
// 这篇文章不会深入讲解 module.exports 和 exports 的关系

module.exports = function () { }

exports.site = 'https://tasaid.com'

module.exports.name = 'linkFly'

例如 nodejs 内置的 events 模块的源码:

bVboJzX?w=1584&h=1094

export default function () { }
 
export const site = 'https://tasaid.com'
 
export const name = 'linkFly'

转存失败重新上传取消clipboard.png

在 ECMAScript 6 中又新增了语法 export 和 export default:

export default function () { }

export const site = 'https://tasaid.com'

export const name = 'linkFly'

到这里画风还比较正常,而大名鼎鼎的 JavaScript 转码编译器 babel 针对 ECMAScript 6 新增的 export default 语法,搞了个 babel-plugin-transform-es2015-modules-commonjs 的转换插件,用于将 ECMAScript 6 转码为 CommonJs 规范的语法:

源码:

export default 42;

编译后:

Object.defineProperty(exports, "__esModule", {
  value: true
});

exports.default = 42;

到这里,我们看到有三种 export 默认值的语法:

// commonjs
module.exports = function () {}

// babel 转码
exports.default = function () {}

// es6
export default function () {}

TypeScript 中的 import

在 TypeScript 中,也有多种 import 的方式。

// commonjs 模块
import * as xx from 'xx'

// es6 模块
import xx from 'xx'

// commonjs 模块,类型声明为 export = xx
import xx = require('xx')

// 没有类型声明,默认导入 any 类型
const xx = require('xx')

在 tsconfig.json 中,allowSyntheticDefaultImports 会影响到 import 语法的类型检查规则,这个下面再说。

import * as xx from 'xx'

import * as xx from 'xx' 的语法来一般都是用来导入使用 module.exports 导出的模块。

import * as path from 'path'

因为 nodejs 中的模块大部分都是通过 module.exportsexports.xx 语法进行导出的。

import xx from 'xx'

默认情况下,import xx from 'xx' 的语法只适用于 ECMAScript 6 的 export default 导出:

模块 foo:

export default function () { 
  console.log('https://tasaid.com') 
}

ES6 模块的导入:

import foo from './foo'
foo()

而前面我们说了,babel 会将 es6 的模块的 export default 语法编译为 exports.default 语法。

而 TypeScript 默认是不识别这种语法的,如果一个模块的导出是 exports.default 导出,如果使用 import xx from 'xx' 的语法导入是会报错的。

clipboard.png

所以在 tsconfig.json 中,有个 allowSyntheticDefaultImports 选项,就是针对这种语法做兼容。

如果设定 allowSyntheticDefaultImports 为 true,则检测导入的模块是否是 ES6 模块,如果不是,则查找模块中是否有 exports.default 导出。

从而达到针对 exports.default 的兼容。

clipboard.png

效果参见这个动画:

bVboJAf?w=1406&h=1172转存失败重新上传取消图片描述

allowSyntheticDefaultImports 选项的,一般情况下我采取的方式是将 deafult 重新命名:

import { default as foo } from 'foo'

import xx = require('xx')

import xx = require('xx') 是用来导入 commonjs 模块的库,特殊的地方在于这个库的类型声明是 export = xx 这种方式导出的:

foo.js 源码:

module.exports = () => { 
  console.log('https://tasaid.com') 
}

foo.d.ts 类型声明文件源码:

declare function foo(): void;
export = foo

bar.ts 引用:

import foo = require('./foo')

foo()

clipboard.png

我在 《[JavaScript 和 TypeScript 交叉口 —— 类型定义文件(*.d.ts)
](https://tasaid.com/blog/20171...》中讲述过 TypeScript 类型声明文件对导入导出的影响。

const xx = require('xx')

当一个模块没有类型声明文件的时候,可以使用 commonjs 原始的 require() 方式来导入模块,这样会默认该模块为 any。

总结

最后我们整体总结下,在 TypeScript 中,有多种 import 的方式,分别对应了 JavaScript 中不同的 export。

// commonjs 模块
import * as xx from 'xx'

// 标准 es6 模块
import xx from 'xx'

// commonjs 模块,类型声明为 export = xx
import xx = require('xx')

// 没有类型声明,默认导入 any 类型
const xx = require('xx')

针对 babel 编译出来的 exports.default 语法,ts 提供了 allowSyntheticDefaultImports 选项可以支持,只不过个人不太推荐。

个人建议将 default 重命名。

import { default as foo } from 'foo'

关于 TypeScript 中类型声明文件(*.d.ts) 对 import 和 export 的影响,可以参考我之前写的 《[JavaScript 和 TypeScript 交叉口 —— 类型定义文件
](https://tasaid.com/blog/20171...》。

原文首发于我的个人网站:听说 - https://tasaid.com,推荐在我的网站阅读更多技术文章。

前端开发 QQ 群:377786580

引用和参考

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vue-typescript-import-dts 是一个用于为 Vue.js 项目TypeScript 文件生成类型声明文件的工具。在 Vue.js 项目使用 TypeScript 进行开发时,我们经常需要为一些第三方库或自定义组件编写类型声明文件,以提供更好的代码提示和类型检查。 使用 vue-typescript-import-dts 工具可以自动分析 TypeScript 文件的导入语句,并根据导入的模块生成对应的类型声明文件。这样,在使用该模块时,IDE 或编辑器就能提供准确的代码补全和类型检查。 例如,假设我们的项目使用了一个名为 axios 的第三方库进行网络请求,但是该库并没有提供类型声明文件。我们可以通过 vue-typescript-import-dts 工具,在我们的 TypeScript 文件导入 axios,并正确配置工具,它将自动为我们生成一个 axios.d.ts 类型声明文件。 具体使用 vue-typescript-import-dts 的步骤如下: 1. 在项目安装 vue-typescript-import-dts,可以使用 npm 或 yarn 命令来安装。 2. 在 TypeScript 文件,使用 import 语句导入需要生成类型声明文件的模块。 3. 在项目根目录下创建一个 .vue-typescript-import-dts.json 配置文件,用来配置生成类型声明文件的规则。可以指定生成的声明文件的输出路径、文件名等。 4. 运行 vue-typescript-import-dts 命令,它会自动扫描 TypeScript 文件的导入语句,并根据配置生成相应的类型声明文件。 这样,在我们编写代码时,IDE 或编辑器就可以准确地为我们提供代码补全和类型检查的功能。这对于提高开发效率和代码质量非常有帮助。 总之,vue-typescript-import-dts 是一个便捷的工具,可以自动为 Vue.js 项目使用的第三方库或自定义组件生成类型声明文件,提供更好的代码提示和类型检查功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值