Skip to content

TypeScript

Oxc 转换器支持将 TypeScript 转换为 JavaScript。

js
import { transform } from "oxc-transform";

const result = await transform("lib.ts", sourceCode, {
  typescript: {
    jsxPragma: "React.createElement",
    jsxPragmaFrag: "React.Fragment",
    onlyRemoveTypeImports: false,
    allowNamespaces: true,
    removeClassFieldsWithoutInitializer: false,
    rewriteImportExtensions: false,
  },
});

verbatimModuleSyntax

默认情况下,TypeScript 在处理未使用导入时的语义与 JavaScript 规范不同。[verbatimModuleSyntax](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) 选项可使 TypeScript 与 JavaScript 规范保持一致。

如果你使用此选项,请确保将 typescript.onlyRemoveTypeImports 选项设置为 true

js
import { transform } from "oxc-transform";

const result = await transform("lib.ts", sourceCode, {
  typescript: {
    onlyRemoveTypeImports: true,
  },
});

useDefineForClassFields

TypeScript 早期对于类字段的语义与 JavaScript 规范不同。useDefineForClassFields 选项可让 TypeScript 与 JavaScript 规范保持一致。如果 tsconfig 中的 target 选项设置为 es2022 或更高版本,则该选项默认启用。

如果你禁用此选项,请确保将 typescript.removeClassFieldsWithoutInitializer 选项和 assumptions.setPublicClassFields 设置为 true

js
import { transform } from "oxc-transform";

const result = await transform("lib.ts", sourceCode, {
  typescript: {
    removeClassFieldsWithoutInitializer: true,
  },
  assumptions: {
    setPublicClassFields: true,
  },
});

装饰器

Oxc 转换器支持转换旧版装饰器。这在 TypeScript 中称为实验性装饰器。

如果你在 tsconfig 中使用了 experimentalDecorators 选项,可以使用 decorators.legacy 选项。
如果你在 tsconfig 中使用了 emitDecoratorMetadata 选项,可以使用 decorators.emitDecoratorMetadata 选项。

js
import { transform } from "oxc-transform";

const result = await transform("lib.ts", sourceCode, {
  decorators: {
    legacy: true,
    emitDecoratorMetadata: true,
  },
});

装饰器元数据:需要类型推断的类型将回退到 Object

由于缺乏完整的类型推断功能,当 Oxc 转换器无法计算装饰器元数据的类型时,会回退到 Object 类型。

例如,以下代码将被转换为如下代码:

ts
import { Something1 } from "./somewhere";

type Something2 = Exclude<string | number, string>;

export class Foo {
  @test
  foo(input1: Something1, input2: Something2) {}
}
js
// 省略辅助函数
import { Something1 } from "./somewhere";
var _ref;
export class Foo {
  foo(input1, input2) {}
}
_decorate(
  [
    test,
    _decorateMetadata("design:type", Function),
    _decorateMetadata("design:paramtypes", [
      typeof (_ref = typeof Something1 !== "undefined" && Something1) === "function"
        ? _ref
        : Object,
      Object, 
    ]),
    _decorateMetadata("design:returntype", void 0),
  ],
  Foo.prototype,
  "foo",
  null,
);
js
// 省略辅助函数
var _a;
import { Something1 } from "./somewhere";
export class Foo {
  foo(input1, input2) {}
}
__decorate(
  [
    test,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [
      typeof (_a = typeof Something1 !== "undefined" && Something1) === "function" ? _a : Object,
      Number, 
    ]),
    __metadata("design:returntype", void 0),
  ],
  Foo.prototype,
  "foo",
  null,
);

此行为与 TypeScript 处理外部类型时的行为一致。

你可以通过调用 Reflect.metadata 显式设置类型:

ts
import { Something1 } from "./somewhere";

type Something2 = Exclude<string | number, string>;

export class Foo {
  @test
  @Reflect.metadata("design:paramtypes", [Something1, Number])
  foo(input1: Something1, input2: Something2) {}
}
js
// 省略辅助函数
import { Something1 } from "./somewhere";
var _ref;
export class Foo {
  foo(input1, input2) {}
}
_decorate(
  [
    test,
    Reflect.metadata("design:paramtypes", [Something1, Number]),
    _decorateMetadata("design:type", Function),
    _decorateMetadata("design:paramtypes", [
      typeof (_ref = typeof Something1 !== "undefined" && Something1) === "function"
        ? _ref
        : Object,
      Object,
    ]),
    _decorateMetadata("design:returntype", void 0),
  ],
  Foo.prototype,
  "foo",
  null,
);

TSX

同样也支持转换 TSX 文件。 更多信息请参见 JSX 转换

重写导入扩展名

如果你在 tsconfig 中使用了 rewriteImportExtensions 选项,可以使用 typescript.rewriteImportExtensions 选项。

js
import { transform } from "oxc-transform";

const result = await transform("lib.ts", sourceCode, {
  typescript: {
    rewriteImportExtensions: "rewrite", // 或 "remove"
  },
});

注意事项

独立模块

由于 Oxc 转换器独立地转换每个文件,某些 TypeScript 功能不被支持。
为避免使用不受支持的功能,你应该在 tsconfig.json 文件中启用 isolatedModules 选项。

部分命名空间支持

TypeScript 具有名为 命名空间 的遗留功能。尽管建议新项目使用 ES 模块,但 Oxc 转换器对命名空间具有部分支持。

不支持使用 varlet 导出变量

使用 varlet 导出变量不被支持。

ts
namespace Foo {
  export let bar = 1; 
}
console.log(Foo.bar);

一种解决方法是使用 const。如果需要变量可变,可以使用带有内部可变性的对象:

ts
namespace Foo {
  export const bar = { value: 1 }; 
}
console.log(Foo.bar.value);

同名命名空间之间不共享作用域

ts
namespace Foo {
  export const bar = 1;
}
namespace Foo {
  export const baz = bar;
}
js
let foo;
(function (_Foo) {
  const bar = (_Foo.bar = 1);
})(Foo || (Foo = {}));
(function (_Foo2) {
  const baz = (_Foo2.baz = bar); 
})(Foo || (Foo = {}));
js
var Foo;
(function (Foo) {
  Foo.bar = 1;
})(Foo || (Foo = {}));
(function (Foo) {
  Foo.baz = Foo.bar; 
})(Foo || (Foo = {}));

在此示例中,第二条命名空间中的 bar 引用指向第一个命名空间中的 bar 变量(TypeScript 编译器输出),但在 Oxc 转换器输出中并不如此。

一种解决方法是显式通过命名空间对象引用:

ts
namespace Foo {
  export const bar = 1;
}
namespace Foo {
  export const baz = Foo.bar; 
}