typescipt 配置精讲 | customConditions

大家好,我是 17。

在看 typescirpt 文档的时候发现有这样一个配置 customConditions。 文档中是这样说的 原文链接。感觉好像是看明白了,但实际上,当你实践的时候,并不容易看到效果。为了看到效果,还需要一些知识做辅助。

node 模块系统

这里是 node 模块系统的文档,原文链接。文档中内容较多,我把 customConditions 配置相关的内容再介绍一下。

子路径导出

当使用 “exports” 字段时, "."子路径用来定义主入口点。

{
  "exports": { 
    ".": "./index.js",
    "./submodule.js": "./src/submodule.js"
  }
} 

比如模块名叫 ”iam17“,对于上面的配置,可以这样导入 exports 定义的 “.”

import iam17 from 'iam17'

iam17 模块还得有默认导出才行

导入 exports 定义的 “./submodule.js”

import submodule from 'iam17/submodule.js';

条件导出

条件导出提供了一种根据特定条件映射到不同路径的方法。子路径导出和条件导出相当于是两重 if

// 判断子路径
if(path){
    // 判断条件
    if(contidtion){
        // 根据 path 和 contidtion 决定导出的内容
    }
}

比如在子路径的基础上,再加上条件

"exports": {
    ".": {
      "import": "./baz.mjs",
      "require": "./biz.mjs"
    }
  }
  • import iam17 from 'iam17 这条语句会命中 "import": "./baz.mjs"
  • const iam17 = require('iam17) 这条语句会命中 "require": "./biz.mjs"

node 系统中内置的条件有下面 5 个,“node-addons”,“node”,“import”,“require”,“default”
。除了系统内置的,还可以自定义条件,文档中叫 用户条件。

node 文档只有一句命令,如果你只看文档,可能还是跑不起来。17 再解释一下。

看下 ts 文档中的例子

"exports": {
  ".": {
    "my-condition": "./foo.mjs",
    "node": "./bar.mjs",
    "import": "./baz.mjs",
    "require": "./biz.mjs"
  }
}

“my-condition” 就是自定义条件。自定义条件必须放在最前面。否则即使你在命令行中指定了node --conditions=my-condition 也没有用。这与用户条件查找规则有关。

node 按顺序 查找符合要求的条件,找到第一个就结束查找。

如果你引用模块的代码是这样的 import iam17 from 'iam17 下面配置的用户条件无法命中

"exports": {
  ".": {
    "node": "./bar.mjs",
    "my-condition": "./foo.mjs",
    "import": "./baz.mjs",
    "require": "./biz.mjs"
  }
}

因为 node 条件也可以用作 import 语句的导出。但如果你把 require 条件放在 my-condition 条件之前是没有关系的。

所以 node --conditions=my-condition 只是让 my-condition 有了参选的资格,能不能选中还要看配置中的优先级。越靠前优先级越高。

node 中的自定义条件导出的使用场景

自定义导出是可以有多个的。自定义导出可以提供灵活性。可以通过编程的方式根据不同的条件使用不同的导出。

typescirpt 使用自定义导出配置

我们先看下官方的例子

{
  "compilerOptions": {
    "target": "es2022",
    "moduleResolution": "bundler",
    "customConditions": ["my-condition"]
  }
}

文档中说 moduleResolution 换成 node16, nodenext 也是可以的。文档并没有解释为什么这三个值可以,而其它的值为什么不可以。17 来补充一下。

moduleResolution 隐含指出代码将要运行在什么样的环境中。

条件导出是 Node v14.9.0 才定稿的,所以 Node(Node10 和 Node 的含义一样)肯定是不行的。既然条件导出是 Node 搞出来的。那么其它的可选值肯定是不行的。

为什么 “Bundler” 又行了呢?因为 “Bundler” 隐含指出代码的的环境是 “打包工具”。 打包工具当然可以理解这个配置。(不理解也可以让他理解)

在 typescirpt 中使用 customConditions 实践

环境准备,需要自己做一个 node 模块,为了叙述方便,这个模块命名为 ‘iam17’,具体就不展开说了,配置文件就用官方的例子

"exports": {
  ".": {
    "my-condition": "./foo.mjs",
    "node": "./bar.mjs",
    "import": "./baz.mjs",
    "require": "./biz.mjs"
  }
}

在 test.ts 中引用这个模块

import iam17 from '1am17'

这时会报错 找不到模块 “iam17” 或其相应的类型声明。这也不奇怪,毕竟我们还没有加类型声明,但是加在哪里呢? 我们先看下,如果不考虑 customConditions 配置,我们要如何给模块加类型声明呢?

  1. 加在 node_modules/@types 下面,一般是用单独的包,直接安装就行。但如果只是测试,直接增加文件 node_modules/@types/iam17/index.d.ts
  2. 写在模块中。

17 经过试验,只有在模块中增加一个名叫 foo.d.mts 的类型文件才行。想想也不难理解,其它的类型定义方式都是固定的,在不添加新规则的情况下,只有这种定义方式才是灵活的。

可能有的同学会有一个疑问,你怎么知道 “./foo.mjs” 的声明文件的名字叫 “foo.d.mts”? 17 告诉大家一个简单的办法:让 typescipt 自己生成 foo.mjs 的说明文件,看看叫什么就行了。同样的,如果不会写声明文件,也可以这样处理,这是学习如何写声明文件的一个方法。

customConditions 的默认条件

就算你没有在 tsconfig.json 中配置条件,ts 也会默认查找这两个条件 types,default,只要写在最前面就行。 比如

"exports": {
  ".": {
    "types": "./foo.mjs",
    "import": "./baz.mjs"
  }
}

最后要注意的是,typescript 中的 customConditions 配置必须和 Node 的 --conditions 参数一起配合使用才行。

到这里文章就结束了,如果还有疑问,欢迎留言。完结,撒花~

  • 31
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IAM17前端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值