You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Babel转译Node.js+TypeScript项目为何未保留可选链语法?

Why is Babel transpiling optional chaining (?.) and nullish coalescing (??) even though my Node.js version supports them?

我明白你的困惑——明明Node.js 14+已经原生支持可选链和空值合并运算符,但Babel还是把它们转成了兼容旧版本的代码,这确实有点反直觉。问题出在你的@babel/preset-env配置上,具体来说是没有明确指定目标运行环境

原因分析

默认情况下,@babel/preset-env会以> 0.25%, not dead作为目标环境(也就是兼容绝大多数仍在使用的浏览器和Node.js版本),所以即使你本地用的是Node.js 14,它还是会转译这些特性来适配更旧的环境。shippedProposals: true只是让Babel支持那些已经被主流环境(包括Node.js)正式纳入的提案语法,但它不会改变预设的目标环境规则——只要目标环境里有不支持该特性的版本,Babel就会转译。

另外你提到移除@babel/preset-typescript后结果还是一样,这很正常:转译这两个运算符的逻辑是由@babel/preset-env(或其依赖的@babel/plugin-proposal-optional-chaining@babel/plugin-proposal-nullish-coalescing-operator插件)处理的,和TypeScript预设无关。

解决方案

你需要在@babel/preset-env的配置里明确指定你的目标Node.js版本,这样Babel就会跳过对已支持特性的转译。有两种方式可以实现:

  1. 指定具体的Node.js版本
    修改你的.babelrc里的@babel/preset-env配置,添加targets.node字段:

    {
      "presets": [
        "@babel/preset-typescript",
        [
          "@babel/preset-env",
          {
            "shippedProposals": true,
            "targets": {
              "node": "14.15.3" // 填写你需要支持的最低Node版本
            }
          }
        ]
      ],
      "plugins": [
        [
          "module-resolver",
          {
            "root": "./src",
            "alias": { "@root": ["./"], "@src": ["./src"] },
            "extensions": [".js", ".ts"]
          }
        ]
      ],
      "sourceMaps": true
    }
    
  2. 自动匹配当前Node版本
    如果你希望Babel自动适配你当前正在使用的Node.js版本,可以用"node": "current"

    {
      "presets": [
        "@babel/preset-typescript",
        [
          "@babel/preset-env",
          {
            "shippedProposals": true,
            "targets": {
              "node": "current"
            }
          }
        ]
      ],
      "plugins": [
        [
          "module-resolver",
          {
            "root": "./src",
            "alias": { "@root": ["./"], "@src": ["./src"] },
            "extensions": [".js", ".ts"]
          }
        ]
      ],
      "sourceMaps": true
    }
    

验证修改

调整配置后,重新运行你的构建命令:

rm -rf build/ && babel src --source-maps --extensions '.js,.ts,.tsx' --ignore '**/*.test.ts' -d build

这时候console.log(x?.ciao ?? 10)应该会保留原生语法,不再被转译。

内容的提问来源于stack exchange,提问作者devamat

火山引擎 最新活动