跳转到主要内容

@babel/plugin-transform-typescript

信息

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

此插件添加了对 TypeScript 编程语言 使用的类型语法的支持。但是,此插件不会添加类型检查传递给它的 JavaScript 的功能。为此,您需要安装和设置 TypeScript。

请注意,尽管 TypeScript 编译器 tsc 积极支持某些 JavaScript 提案,例如可选链(?.)、空值合并运算符(??)和类属性(this.#x),但此预设不包括这些功能,因为它们不是仅在 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"]
}

通过 CLI

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

历史
版本更改
v7.5.0添加了 allowNamespaces,默认为 false
v7.13.0默认为 true

启用 TypeScript 命名空间的编译。

disallowAmbiguousJSXLike

boolean,默认为 false

添加于:v7.16.0

即使未启用 JSX 解析,此选项也不允许使用与 JSX 不明确的语法(<X> y 类型断言和 <X>() => {} 类型参数)。它与解析 .mts.mjs 文件时 tsc 的行为相匹配。

dts

boolean,默认为 false

添加于:v7.20.0

此选项将启用在 TypeScript 环境上下文中进行解析,其中某些语法具有不同的规则(例如 .d.ts 文件和 declare module 块内部)。有关环境上下文的更多信息,请参阅 官方手册TypeScript 深入探讨

isTSX

boolean,默认为 false

强制启用 jsx 解析。否则,尖括号将被视为 TypeScript 的旧版类型断言 var foo = <string>bar;。此外,isTSX: true 需要 allExtensions: true

jsxPragma

string,默认为 React

替换编译 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 您可以使用 strictMode 解析器选项

    JavaScript
    module.exports = {
    parserOpts: { strictMode: true },
    };
  • --downlevelIteration 您可以使用 @babel/plugin-transform-for-of 插件。如果您正在使用 @babel/preset-env,则在您的编译目标不支持 for...of 时,它已经使用迭代器进行了转换。

  • --emitDecoratorMetadata 官方 Babel 包不支持此选项,因为它是一个特定于 TypeScript 的添加,而不是装饰器提案的一部分。如果您依赖此功能,则可以使用社区插件 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单个插件
    false/
    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 已启用,但是,Babel 本身提供了一些替代方法来设置许多 tsconfig.json 选项

  3. :为什么 Babel 不允许导出 varlet 声明的变量?

    :TypeScript 编译器会根据值是否被修改来动态更改这些变量的使用方式。最终,这取决于类型模型,超出了 Babel 的范围。一种尽力而为的实现方法是将变量的上下文相关用法转换为始终使用 Namespace.Value 版本而不是 Value,以防它在当前文件之外被修改。因此,允许 Babel 中使用 varlet(因为转换尚未编写)很可能会在使用时出现错误,就好像它不是 const 一样。

部分命名空间支持

如果您现有的代码使用了仅限 TypeScript 的 命名空间 特性。Babel 支持 TypeScript 命名空间特性的一个子集。如果您正在考虑编写使用命名空间的新代码,建议改用 ES2015 的 import/export。它 不会消失,但有现代的替代方案。

  • 仅类型 namespace 应使用 declare 标记,随后将被安全删除。

  • namespace 中使用 varlet export 变量将导致错误:“Babel 不支持导出非 const 变量的命名空间。请改为使用 const 或...”

    解决方法:使用 const。如果需要某种形式的修改,请显式使用具有内部可修改性的对象。

  • namespace 不会共享其作用域。在 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;
    }