Typescript配置文件(tsconfig.json)详解系列六:allowImportingTsExtensions

前言

本文使用的Typescript版本为5.5.2

配置

{
    compilerOptions: {
        "allowImportingTsExtensions": true
    }
}

说明

allowImportingTsExtensionstypescript@5.x后加入的字段。

配置启用后,import其他模块时允许携带.ts.mts和 .tsx等typescript支持的扩展名

// 默认的引入方式,不需要加ts后缀名
import {a as a1} from './demo2'

import {a as a2} from './demo2.ts'
import {a as a3} from './demo1.tsx'
import {a as a4} from './demo3.mts'
import {a as a5} from './demo4.cts'

export {a1, a2, a3, a4, a5}

不开启的时候会报错如下:

ts/index.ts:4:23 - error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.

4 import {a as a2} from './demo2.ts'
                        ~~~~~~~~~~~~

ts/index.ts:5:23 - error TS5097: An import path can only end with a '.tsx' extension when 'allowImportingTsExtensions' is enabled.

5 import {a as a3} from './demo1.tsx'
                        ~~~~~~~~~~~~~

ts/index.ts:6:23 - error TS5097: An import path can only end with a '.mts' extension when 'allowImportingTsExtensions' is enabled.

6 import {a as a4} from './demo3.mts'
                        ~~~~~~~~~~~~~

ts/index.ts:7:23 - error TS5097: An import path can only end with a '.cts' extension when 'allowImportingTsExtensions' is enabled.

7 import {a as a5} from './demo4.cts'
                        ~~~~~~~~~~~~~

此标志仅在启用 --noEmit(不输出编译后的js文件)--emitDeclarationOnly(只编译输出类型声明文件d.ts) 时才允许。

编译后为*.d.ts(--emitDeclarationOnly),编译后的结果如下(看起来文件后缀名还会被保留):

import { a as a1 } from './demo2';
import { a as a2 } from './demo2.ts';
import { a as a3 } from './demo1.tsx';
import { a as a4 } from './demo3.mts';
import { a as a5 } from './demo4.cts';
export { a1, a2, a3, a4, a5 };

后记

我们来看看不启用allowImportingTsExtensions的效果,在不引入后缀名的情况下,效果如下

// 默认的引入方式,不需要加ts后缀名
import {a as a1} from './demo1'  // tsx
import {a as a2} from './demo2'  // ts
import {a as a3} from './demo3'  // mts
import {a as a4} from './demo4'  // cts

console.log(a1, a2, a3, a4)

tsconfig.json配置如下:

{
  "compilerOptions": {
      "allowImportingTsExtensions": false,
      "jsx": "preserve"  // 开启jsx支持,
      "module": "NodeNext",
      "moduleResolution": "NodeNext"
  }
}

 编译报错如下(引入jsx没有报错):

ts/index.ts:4:23 - error TS2307: Cannot find module './demo3' or its corresponding type declarations.

4 import {a as a3} from './demo3'
                        ~~~~~~~~~

ts/index.ts:5:23 - error TS2307: Cannot find module './demo4' or its corresponding type declarations.

5 import {a as a4} from './demo4'

 这里需要将demo3和demo4的后缀修改以下(使用 TypeScript 时,您需要使用文件扩展名的JAVASCRIPT版本导入代码。)。这个设定有点奇怪,不过确实typescript永远不会修改你在*.ts中导入的文件后缀和路径。

// 默认的引入方式,不需要加ts后缀名
import {a as a1} from './demo1'
import {a as a2} from './demo2'
// importing from demo3.mts
import {a as a3} from './demo3.mjs'  // 导入的是*.mts, 使用解析后的js后缀导入
// importing from demo4.mts
import {a as a4} from './demo4.cjs'  // 导入的是*.cts, 使用解析后的js后缀导入

此时会报错如下:

ts/index.ts:4:23 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("./demo3.mjs")' call instead.
  To convert this file to an ECMAScript module, change its file extension to '.mts' or create a local package.json file with `{ "type": "module" }`.

4 import {a as a3} from './demo3.mjs'

这是因为我的package.json设置的type类型为commonjs,入口文件index.ts的后缀为*.ts,所以他不能导入ESM模块系统的文件(*.mts/*.mjs),我们将index.ts修改为index.mts,此时会报错:

ts/index.mts:2:23 - error TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './demo1.jsx'?

2 import {a as a1} from './demo1'
                        ~~~~~~~~~

ts/index.mts:3:23 - error TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './demo2.js'?

3 import {a as a2} from './demo2'

我们根据提示补全了这两个引入的后缀:

// 默认的引入方式,不需要加ts后缀名
import {a as a1} from './demo1.js'
import {a as a2} from './demo2.jsx'
import {a as a3} from './demo3.mjs'
import {a as a4} from './demo4.cjs'

console.log(a1, a2, a3, a4)

此时就不报错了,可以正常编译了。

总结

  • 如果不使用allowImportingTsExtensions的时候,在导入文件的时候需要加上typescript编译后的文件后缀。
  • 如果使用了allowImportingTsExtensions就不能输出编译文件,只能输出声明文件(*.d.ts)。

原因分析:

因为typescript在编译后的js文件中不会对导入模块的地址和文件后缀做任何修改,所以如果开启了allowImportingTsExtensions之后编译的js文件的导入文件后缀仍然是.ts, .mts和 .tsx等,无法被js正常执行。

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值