跳至主内容

@babel/plugin-transform-typescript

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

信息

此插件已包含在 @babel/preset-typescript

此插件支持 TypeScript 编程语言 使用的类型语法,但不会添加类型检查能力。如需类型检查功能,您需额外安装并配置 TypeScript。

请注意:虽然 TypeScript 编译器 tsc 支持可选链 (?.)、空值合并 (??) 和类私有字段 (this.#x) 等 JavaScript 提案,但本预设不包含这些特性,因为它们并非 TypeScript 专属的类型语法。如需转译这些特性,建议搭配使用 preset-envpreset-typescript

示例

输入

const x: number = 0;

输出

const x = 0;

安装

npm install --save-dev @babel/plugin-transform-typescript

用法

通过配置文件(推荐)

babel.config.json
{
"plugins": ["@babel/plugin-transform-typescript"]
}

通过命令行

Shell
babel --plugins @babel/plugin-transform-typescript script.js

通过 Node API

JavaScript
require("@babel/core").transformSync("code", {
plugins: ["@babel/plugin-transform-typescript"],
});

配置选项

allowDeclareFields

boolean,默认值 false

添加于 v7.7.0

备注

此功能将在 Babel 8 中默认启用

启用后,仅当类型声明字段带有 declare 修饰符前缀时才会被移除:

JavaScript
class A {
declare foo: string; // Removed
bar: string; // Initialized to undefined
}

allowNamespaces

boolean 类型,默认值为 true

History
VersionChanges
v7.5.0Added allowNamespaces, defaults to false
v7.13.0defaults to true

启用 TypeScript 命名空间的编译支持。

disallowAmbiguousJSXLike

boolean,默认值 false

添加于:v7.16.0

即使未启用 JSX 解析,此选项也会禁止使用可能与 JSX 产生歧义的语法(<X> y 类型断言和 <X>() => {} 类型参数)。其行为与解析 .mts.mjs 文件时的 tsc 保持一致。

dts

boolean,默认值 false

添加于:v7.20.0

此选项将启用 TypeScript 环境上下文(ambient context)中的解析模式,该模式下特定语法遵循不同规则(如 .d.ts 文件及 declare module 块内部)。更多关于环境上下文的信息,请参阅官方手册《TypeScript Deep Dive》

isTSX

boolean,默认值 false

强制启用 jsx 解析。否则尖括号将被视为 TypeScript 的旧式类型断言 var foo = <string>bar;。注意:isTSX: true 需配合 allExtensions: true 使用。

jsxPragma

string,默认值 React.createElement

替换编译 JSX 表达式时使用的函数。这有助于识别该导入并非类型导入,不应被移除。

jsxPragmaFrag

string,默认值 React.Fragment

替换编译 JSX 片段表达式时使用的函数。这有助于识别该导入并非类型导入,不应被移除。

onlyRemoveTypeImports

boolean,默认值 false

添加于:v7.9.0

设为 true 时,转换器仅移除纯类型导入(TypeScript 3.8 引入)。仅当使用 TypeScript ≥ 3.8 时启用此选项。

JavaScript
class A {
declare foo: string; // Removed
bar: string; // Initialized to undefined
prop?: string; // Initialized to undefined
prop1!: string // Initialized to undefined
}

optimizeConstEnums

boolean,默认值 false

添加于:v7.15.0

设为 true 时,Babel 将内联枚举值而非使用常规的 enum 输出:

// Input
const enum Animals {
Fish,
}
console.log(Animals.Fish);

// Default output
var Animals;

(function(Animals) {
Animals[(Animals["Fish"] = 0)] = "Fish";
})(Animals || (Animals = {}));

console.log(Animals.Fish);

// `optimizeConstEnums` output
console.log(0);

此选项不同于 TypeScript 的 --isolatedModules 行为(会忽略 const 修饰符并按常规枚举编译),使 Babel 行为与 TypeScript 默认行为保持一致。

但导出 const enum 时,Babel 会将其编译为普通对象字面量,避免依赖跨文件分析:

// Input
export const enum Animals {
Fish,
}

// `optimizeConstEnums` output
export var Animals = {
Fish: 0,
};

TypeScript 编译器选项

官方 TypeScript 编译器提供多种配置选项用于控制编译和类型检查行为。虽然部分选项不适用,但某些行为仍具参考价值,可通过 Babel 的配置选项或插件实现等效功能。

  • --alwaysStrict 可通过 parser 选项strictMode 实现:

    JavaScript
    module.exports = {
    parserOpts: { strictMode: true },
    };
  • --downlevelIteration 可使用 @babel/plugin-transform-for-of 插件。若已使用 @babel/preset-env,当编译目标环境不支持 for...of 时,其将自动通过迭代器转译。

  • --emitDecoratorMetadata 此选项为 TypeScript 特有功能,不属装饰器提案标准,官方 Babel 包不提供支持。如需此功能,可使用社区插件 babel-plugin-transform-typescript-metadata

  • --esModuleInterop 这是 Babel 转译 ECMAScript 模块时的默认行为。

  • --experimentalDecorators 此选项启用对"传统"装饰器提案的支持。您可以通过 @babel/plugin-proposal-decorators 插件在 Babel 中启用此功能,但请注意两者存在细微差异。

    JavaScript
    module.exports = {
    plugins: [["@babel/plugin-proposal-decorators", { legacy: true }]],
    };
  • --importHelpers 这相当于 @babel/plugin-transform-runtime 包的功能。

  • ---importsNotUsedAsValues 您可以使用 onlyRemoveTypeImports 选项来模拟此行为。onlyRemoveTypeImports: true 相当于 importsNotUsedAsValues: preserve,而 onlyRemoveTypeImports: false 相当于 importsNotUsedAsValues: remove。没有与 importsNotUsedAsValues: error 等效的选项。

  • --inlineSourceMap 您可以在 babel.config.json 文件中设置 sourceMaps: "inline" 选项。

  • --isolatedModules 这是 Babel 的默认行为,且无法关闭,因为 Babel 不支持跨文件分析。

  • --jsx JSX 支持由另一个插件提供。 若希望输出保留 JSX 代码(即 --jsx preserve),需使用 @babel/plugin-syntax-jsx 插件;若需转译为标准 JavaScript(即 --jsx react--jsx react-native),则应使用 @babel/plugin-transform-react-jsx 插件。

  • --jsxFactory 可通过 @babel/plugin-transform-react-jsx 包的 pragma 选项进行自定义。同时还需设置本插件的 jsxPragma 选项。

  • --module, -m 若使用打包工具(如 Webpack 或 Rollup),此选项会自动设置。 若使用 @babel/preset-env,可通过其 modules 选项配置;否则需加载特定插件。

    --module@babel/preset-envmodules单独插件
    Nonefalse/
    CommonJS"commonjs""cjs"@babel/plugin-transform-modules-commonjs
    AMD"amd"@babel/plugin-transform-modules-amd
    System"systemjs"@babel/plugin-transform-modules-systemjs
    UMD"umd"@babel/plugin-transform-modules-umd
    ES6ES2015false/
  • --outDir 使用 @babel/cli 时,可通过 --out-dir 选项进行设置。

  • --outFile Babel 不支持合并输出文件,需使用打包工具(如 Webpack、Rollup 或 Parcel)。 使用 @babel/cli 时,可通过 --out-file 选项编译单个文件。

  • --sourceMap 可使用顶层的 sourceMaps: true 选项

  • --target Babel 不支持指定语言的具体版本,但你可以通过 @babel/preset-env 选择目标引擎。如果愿意,也可以为每个 ECMAScript 特性单独启用对应插件

  • --useDefineForClassFields 你可以使用 setPublicClassFields 编译假设来复现此行为。

  • --watch, -w 使用 @babel/cli 时,可通过 --watch 选项实现监听功能。

注意事项

由于 TypeScript 语言的某些特性依赖于完整的类型系统在运行时进行动态修改,以下注意事项篇幅较长。但值得注意是,其中部分特性仅出现在旧版 TypeScript 代码库中,现代 JavaScript 已提供等效替代方案。

  1. Babel 不进行类型检查,因此语法正确但无法通过 TypeScript 类型检查的代码仍可能被转换,且常产生非预期或无效结果。

  2. tsconfig.json 的修改不会影响 Babel。构建过程始终表现为启用了 isolatedModules 的状态,但许多 tsconfig.json 选项可通过 Babel 原生方式配置。

  3. :为何 Babel 不允许导出 varlet

    :TypeScript 编译器会根据变量值是否被修改动态改变其使用方式。这本质上依赖于类型模型,超出 Babel 的处理范围。若采用折中方案,需将变量的上下文相关用法统一转换为 Namespace.Value 形式(而非直接使用 Value),以防止跨文件修改导致的问题。由于相关转换尚未实现,允许导出 varlet 极可能在使用时产生非预期行为(如同它们不是 const)。

命名空间支持限制

若现有代码使用了 TypeScript 特有的命名空间特性,Babel 仅支持其功能子集。编写新代码时建议使用 ES2015 的 import/export 替代命名空间。命名空间特性不会被移除,但存在更现代的替代方案。

  • 纯类型声明的 namespace 应标记为 declare,后续会被安全移除。

  • 使用 varletnamespaceexport 导出变量将导致错误:"Babel 不支持导出非 const 的命名空间,请改用 const 或..."

    解决方案:使用 const。如需可变性,请显式使用具有内部可变性的对象。

  • namespaces 不会共享作用域。在 TypeScript 中,引用一个 namespace 扩展的上下文项时无需显式限定是有效的,编译器会自动添加限定符。但在 Babel 中没有类型模型,无法动态更改引用以匹配父对象的既定类型。

    参考以下代码:

    namespace N {
    export const V = 1;
    }
    namespace N {
    export const W = V;
    }

    TypeScript 编译器会将其编译为类似这样:

    JavaScript
    var N = {};
    (function(N) {
    N.V = 1;
    })(N);
    (function(N) {
    N.W = N.V;
    })(N);

    而 Babel 会将其转换为:

    JavaScript
    var N;
    (function(_N) {
    const V = (_N = 1);
    })(N || (N = {}));
    (function(_N) {
    const W = V;
    })(N || (N = {}));

    由于 Babel 不理解 N 的类型,对 V 的引用将变为 undefined 导致错误。

    解决方法:显式引用不在同一命名空间定义中的值,即使按照 TypeScript 规则它们应在作用域内。例如:

    namespace N {
    export const V = 1;
    }
    namespace N {
    export const W = N.V;
    }

    或:

    namespace N {
    export const V = 1;
    export const W = V;
    }