Skip to main content

@babel/plugin-transform-typescript

信息

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

¥This plugin is included in @babel/preset-typescript

这个插件增加了对 TypeScript 编程语言 使用的类型语法的支持。但是,这个插件没有添加对传递给它的 JavaScript 进行类型检查的能力。为此,你需要安装和设置 TypeScript。

¥This plugin adds support for the types syntax used by the TypeScript programming language. However, this plugin does not add the ability to type-check the JavaScript passed to it. For that, you will need to install and set up TypeScript.

请注意,尽管 TypeScript 编译器 tsc 积极支持某些 JavaScript 提议,例如可选链 (?.)、空值合并 (??) 和类属性 (this.#x),但此预设不包含这些功能,因为它们不是仅在 TypeScript 中可用的类型语法.如果你想转译这些功能,我们建议使用 preset-envpreset-typescript

¥Note that although the TypeScript compiler tsc actively supports certain JavaScript proposals such as optional chaining (?.), nullish coalescing (??) and class properties (this.#x), this preset does not include these features because they are not the types syntax available in TypeScript only. We recommend using preset-env with preset-typescript if you want to transpile these features.

示例

¥Example

输入

¥In

const x: number = 0;

输出

¥Out

const x = 0;

安装

¥Installation

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

用法

¥Usage

¥With a configuration file (Recommended)

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

通过 CLI

¥Via CLI

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

通过 Node API

¥Via Node API

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

选项

¥Options

allowDeclareFields

boolean,默认为 false

¥boolean, defaults to false

添加于 v7.7.0

¥Added in v7.7.0

注意

这将在 Babel 8 中默认启用

¥This will be enabled by default in Babel 8

启用后,仅类型的类字段仅在以 declare 修饰符为前缀时才会被删除:

¥When enabled, type-only class fields are only removed if they are prefixed with the declare modifier:

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

allowNamespaces

boolean,默认为 true

¥boolean, defaults to true.

History
版本变化
v7.5.0添加了 allowNamespaces,默认为 false
v7.13.0默认为 true

启用 TypeScript 命名空间的编译。

¥Enables compilation of TypeScript namespaces.

disallowAmbiguousJSXLike

boolean,默认为 false

¥boolean, defaults to false

添加于:v7.16.0

¥Added in: v7.16.0

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

¥Even when JSX parsing is not enabled, this option disallows using syntax that would be ambiguous with JSX (<X> y type assertions and <X>() => {} type arguments). It matches the tsc behavior when parsing .mts and .mjs files.

dts

boolean,默认为 false

¥boolean, defaults to false

添加于:v7.20.0

¥Added in: v7.20.0

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

¥This option will enable parsing within a TypeScript ambient context, where certain syntax have different rules (like .d.ts files and inside declare module blocks). Please see Official Handbook and TypeScript Deep Dive for more information about ambient contexts.

isTSX

boolean,默认为 false

¥boolean, defaults to false

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

¥Forcibly enables jsx parsing. Otherwise angle brackets will be treated as TypeScript's legacy type assertion var foo = <string>bar;. Also, isTSX: true requires allExtensions: true.

jsxPragma

string,默认为 React

¥string, defaults to React

替换编译 JSX 表达式时使用的函数。这是为了让我们知道导入不是类型导入,不应该被删除。

¥Replace the function used when compiling JSX expressions. This is so that we know that the import is not a type import, and should not be removed.

jsxPragmaFrag

string,默认为 React.Fragment

¥string, defaults to React.Fragment

替换编译 JSX 片段表达式时使用的函数。这是为了让我们知道导入不是类型导入,不应该被删除。

¥Replace the function used when compiling JSX fragment expressions. This is so that we know that the import is not a type import, and should not be removed.

onlyRemoveTypeImports

boolean,默认为 false

¥boolean, defaults to false

添加于:v7.9.0

¥Added in: v7.9.0

当设置为 true 时,转换只会删除 仅类型导入(在 TypeScript 3.8 中引入)。仅当你使用 TypeScript >= 3.8 时才应使用此选项。

¥When set to true, the transform will only remove type-only imports (introduced in TypeScript 3.8). This should only be used if you are using 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

¥boolean, defaults to false

添加于:v7.15.0

¥Added in: v7.15.0

当设置为 true 时,Babel 将内联枚举值而不是使用通常的 enum 输​​出:

¥When set to true, Babel will inline enum values rather than using the usual enum output:

// 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 的默认行为对齐。

¥This option differs from TypeScript's --isolatedModules behavior, which ignores the const modifier and compiles them as normal enums, and aligns Babel's behavior with TypeScript's default behavior.

但是,当导出 const enum Babel 时,会将其编译为纯对象字面量,以便在编译时不需要依赖跨文件分析:

¥However, when exporting a const enum Babel will compile it to a plain object literal so that it doesn't need to rely on cross-file analysis when compiling it:

// Input
export const enum Animals {
Fish,
}

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

TypeScript 编译器选项

¥TypeScript Compiler Options

官方的 TypeScript 编译器有许多 选项 用于配置它的编译方式和类型检查。虽然许多不适用,但某些行为可能有用,并且它们在 Babel 中的等价物可以通过一些配置选项或插件来启用。

¥The official TypeScript compiler has many options for configuring how it compiles and type checks. While many don't apply, some behaviors might be useful and their equivalents in Babel can be enabled by some configuration options or plugins.

  • --alwaysStrict 你可以使用 strictMode 解析器选项

    ¥--alwaysStrict You can use the strictMode parser option:

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

    ¥--downlevelIteration You can use the @babel/plugin-transform-for-of plugin. If you are using @babel/preset-env, for...of is already transpiled using iterators when it isn't supported by your compilation target(s).

  • --emitDecoratorMetadata 官方 Babel 包不支持此选项,因为它是特定于 TypeScript 的附加项,而不是装饰器提案的一部分。如果你依赖这个特性,你可以使用社区插件 babel-plugin-transform-typescript-metadata

    ¥--emitDecoratorMetadata This option isn't supported by an official Babel package since it is a TypeScript-specific addition and not part of the decorators proposal. If you rely on this feature, you can use the community plugin babel-plugin-transform-typescript-metadata.

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

    ¥--esModuleInterop This is the default behavior of Babel when transpiling ECMAScript modules.

  • --experimentalDecorators 此选项启用对 "legacy" 装饰器提案的支持。你可以使用 @babel/plugin-proposal-decorators 插件在 Babel 中启用它,但请注意,存在一些细微差别。

    ¥--experimentalDecorators This option enables support for the "legacy" decorator proposal. You can enable it in Babel using the @babel/plugin-proposal-decorators plugin, but please be aware, there are some minor differences.

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

    ¥--importHelpers This is the equivalent of the @babel/plugin-transform-runtime package.

  • ---importsNotUsedAsValues 你可以使用 onlyRemoveTypeImports 选项来复制此行为。onlyRemoveTypeImports: true 等价于 importsNotUsedAsValues: preserve,而 onlyRemoveTypeImports: false 等价于 importsNotUsedAsValues: removeimportsNotUsedAsValues: error 没有等价物。

    ¥---importsNotUsedAsValues You can use the onlyRemoveTypeImports option to replicate this behavior. onlyRemoveTypeImports: true is equivalent to importsNotUsedAsValues: preserve, while onlyRemoveTypeImports: false is equivalent to importsNotUsedAsValues: remove. There is no equivalent for importsNotUsedAsValues: error.

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

    ¥--inlineSourceMap You can set the sourceMaps: "inline" option in your babel.config.json file.

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

    ¥--isolatedModules This is the default Babel behavior, and it can't be turned off because Babel doesn't support cross-file analysis.

  • --jsx JSX 支持是使用另一个插件提供的。如果你想让你的输出包含 JSX 代码(即 --jsx preserve),你需要 @babel/plugin-syntax-jsx 插件;如果你想将它转换为标准的 JavaScript(即 --jsx react--jsx react-native),你应该使用 @babel/plugin-transform-react-jsx 插件。

    ¥--jsx JSX support is provided using another plugin. If you want your output to contains JSX code (i.e. --jsx preserve), you need the @babel/plugin-syntax-jsx plugin; if you want to transpile it to standard JavaScript (i.e. --jsx react or --jsx react-native), you should use the @babel/plugin-transform-react-jsx plugin.

  • --jsxFactory 它可以使用 @babel/plugin-transform-react-jsx 包的 pragma 选项 进行定制。你还需要设置此插件的 jsxPragma 选项。

    ¥--jsxFactory It can be customized using the pragma option of the @babel/plugin-transform-react-jsx package. You also need to set the jsxPragma option of this plugin.

  • --module, -m 如果你使用打包器(Webpack 或 Rollup),此选项会自动设置。如果你使用的是 @babel/preset-env,则可以使用 modules 选项;否则你可以加载特定的插件。

    ¥--module, -m If you are using a bundler (Webpack or Rollup), this option is set automatically. If you are using @babel/preset-env, you can use the modules option; otherwise you can load the specific plugin.

    --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 选项

    ¥--outDir When using @babel/cli, you can set the --out-dir option.

  • --outFile Babel 不支持连接输出文件:你应该为此使用打包器(如 Webpack、Rollup 或 Parcel)。使用 @babel/cli 时,可以使用 --out-file 选项 编译单个文件。

    ¥--outFile Babel doesn't support concatenating output files: you should use a bundler (like Webpack, Rollup or Parcel) for that. When using @babel/cli, you can compile a single file using the --out-file option.

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

    ¥--sourceMap You can use the top-level sourceMaps: true option.

  • --target Babel 不支持针对语言的特定版本,但你可以使用 @babel/preset-env 选择要针对的引擎。如果你愿意,可以为每个 ECMAScript 功能启用 个人插件

    ¥--target Babel doesn't support targeting a specific version of the language, but you can choose which engines you want to target using @babel/preset-env. If you prefer, you can enable individual plugins for every ECMAScript feature.

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

    ¥--useDefineForClassFields You can use the setPublicClassFields assumption to replicate this behavior.

  • --watch-w 使用 @babel/cli 时,可以指定 --watch 选项

    ¥--watch, -w When using @babel/cli, you can specify the --watch option.

注意事项

¥Caveats

因为 TypeScript 语言的一些特性依赖于完整的类型系统,可以在运行时进行更改。这部分注意事项很长,但是值得注意的是,其中一些功能仅在较旧的 TypeScript 代码库中找到,并且具有你可能已经在使用的现代 JavaScript 等效项。

¥Because there are features of the TypeScript language which rely on the full type-system to be available to make changes at runtime. This section of caveats is quite long, however, it's worth noting that a few of these features are only found in older TypeScript codebases and have modern JavaScript equivalents which you are probably already using.

  1. 由于 Babel 不进行类型检查,因此语法正确但无法通过 TypeScript 类型检查的代码可能会成功转换,并且通常以意想不到或无效的方式进行转换。

    ¥Since Babel does not type-check, code which is syntactically correct, but would fail the TypeScript type-checking may successfully get transformed, and often in unexpected or invalid ways.

  2. 对你的 tsconfig.json 所做的更改不会反映在 babel 中。构建过程将始终表现得好像 isolatedModules 已打开,但是有 Babel-native 替代方法来设置很多 tsconfig.json options

    ¥Changes to your tsconfig.json are not reflected in babel. The build process will always behave as though isolatedModules is turned on, there are Babel-native alternative ways to set a lot of the tsconfig.json options however.

  3. 问:为什么 Babel 不允许导出 varlet

    ¥Q: Why doesn't Babel allow export of a var or let?

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

    ¥A: The TypeScript compiler dynamically changes how these variables are used depending on whether or not the value is mutated. Ultimately, this depends on a type-model and is outside the scope of Babel. A best-effort implementation would transform context-dependent usages of the variable to always use the Namespace.Value version instead of Value, in case it was mutated outside of the current file. Allowing var or let from Babel (as the transform is not-yet-written) is therefore is more likely than not to present itself as a bug when used as-if it was not const.

公正的命名空间支持

¥Impartial Namespace Support

如果你有现有代码使用 TypeScript-only namespace 功能。Babel 支持 TypeScript 命名空间功能的一个子集。如果你正在考虑编写使用命名空间的新代码,建议使用 ES2015 import/export。它是 不会离开,但有现代替代品。

¥If you have existing code which uses the TypeScript-only namespace features. Babel supports a subset of TypeScript's namespace features. If you are considering writing new code which uses namespace, using the ES2015 import/export is recommended instead. It's not going away, but there are modern alternatives.

  • 仅限类型的 namespace 应标记为 declare,随后将被安全删除。

    ¥Type-only namespaces should be marked with declare and will subsequently be safely removed.

  • namespace 中使用 varlet 对变量进行 export 操作会导致错误:“Babel 不支持导出非常量的命名空间。更改为 const 或...”

    ¥exporting a variable using var or let in a namespace will result in an error: "Namespaces exporting non-const are not supported by Babel. Change to const or ..."

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

    ¥Workaround: Use const. If some form of mutation is required, explicitly use an object with internal mutability.

  • namespace 不会分享他们的范围。在 TypeScript 中,引用 namespace 扩展的上下文项而不限定它们是有效的,编译器将添加限定符。在 Babel 中,没有 type-model,不可能动态改变引用来匹配父对象的既定类型。

    ¥namespaces will not share their scope. In TypeScript, it is valid to refer to contextual items that a namespace extends without qualifying them, and the compiler will add the qualifier. In Babel, there is no type-model, and it is impossible to dynamically change references to match the established type of the parent object.

    考虑这段代码:

    ¥Consider this code:

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

    TypeScript 编译器将其编译为如下内容:

    ¥The TypeScript compiler compiles it to something like this:

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

    而 Babel 会将它转换成这样的东西:

    ¥While Babel will transform it to something like this:

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

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

    ¥As Babel doesn't understand the type of N, the reference to V will be undefined resulting in an error.

    解决方法:显式引用不在同一命名空间定义中的值,即使它们在 TypeScript 的范围内。示例:

    ¥Workaround: Explicitly refer to values not in the same namespace definition, even if they would be in the scope according to TypeScript. Examples:

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

    或者:

    ¥Or:

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