TypeScript
Oxc transformer 支持将 TypeScript 转换为 JavaScript。
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,
optimizeConstEnums: false,
optimizeEnums: false,
},
});verbatimModuleSyntax
默认情况下,TypeScript 会以不同于 JavaScript 规范的语义移除未使用的导入。 verbatimModuleSyntax 选项会告诉 TypeScript 与 JavaScript 规范保持一致。
如果你正在使用此选项,请确保将 typescript.onlyRemoveTypeImports 选项设置为 true。
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。
import { transform } from "oxc-transform";
const result = await transform("lib.ts", sourceCode, {
typescript: {
removeClassFieldsWithoutInitializer: true,
},
assumptions: {
setPublicClassFields: true,
},
});装饰器
Oxc transformer 支持转换旧版装饰器。这在 TypeScript 中称为实验性装饰器。
如果你在 tsconfig 中使用 experimentalDecorators 选项,可以使用 decorator.legacy 选项。 如果你在 tsconfig 中使用 emitDecoratorMetadata 选项,可以使用 decorator.emitDecoratorMetadata 选项。
import { transform } from "oxc-transform";
const result = await transform("lib.ts", sourceCode, {
decorator: {
legacy: true,
emitDecoratorMetadata: true,
},
});装饰器元数据:需要类型推断的类型将回退为 Object
由于缺少完整的类型推断功能,如果 Oxc transformer 无法计算装饰器元数据的类型,它将回退为 Object 类型。
例如,下面的代码将会被转换为以下代码:
import { Something1 } from "./somewhere";
type Something2 = Exclude<string | number, string>;
export class Foo {
@test
foo(input1: Something1, input2: Something2) {}
}// omit helper functions
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,
);// omit helper functions
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 显式设置这些类型:
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) {}
}// omit helper functions
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 transform。
重写导入扩展名
如果你在 tsconfig 中使用 rewriteRelativeImportExtensions 选项,可以使用 typescript.rewriteImportExtensions 选项。
"rewrite"或true:将.ts和.tsx重写为.js,将.mts重写为.mjs,将.cts重写为.cjs。"remove":完全移除.ts/.tsx/.mts/.cts扩展名。false(默认):不做任何更改。
import { transform } from "oxc-transform";
const result = await transform("lib.ts", sourceCode, {
typescript: {
rewriteImportExtensions: "rewrite", // 或 "remove", true, false
},
});优化枚举
Oxc transformer 可以通过在使用位置内联枚举成员值来优化枚举。
optimizeConstEnums:内联const enum的值并移除其声明。optimizeEnums:当所有成员都满足 const enum 约束(即其值可以静态求值)时,内联普通(非 const)枚举成员的访问。若非导出的枚举声明的所有成员都可求值,且不存在将该枚举作为运行时值的引用,也会将其移除。
import { transform } from "oxc-transform";
const result = await transform("lib.ts", sourceCode, {
typescript: {
optimizeConstEnums: true,
optimizeEnums: true,
},
});声明
在转换输出旁边生成 .d.ts 声明文件。源文件必须符合所有 isolatedDeclarations 要求。
import { transform } from "oxc-transform";
const result = await transform("lib.ts", sourceCode, {
typescript: {
declaration: {
stripInternal: false,
},
},
});
console.log(result.declaration); // .d.ts 内容
console.log(result.declarationMap); // 声明源映射(如果启用了 sourcemap)注意事项
独立模块
由于 Oxc transformer 会独立转换每个文件,因此某些 TypeScript 特性不受支持。 为避免使用不受支持的特性,你应该在 tsconfig.json 文件中启用 isolatedModules 选项。
部分命名空间支持
TypeScript 有一个称为 namespaces 的旧特性。虽然新项目推荐使用 ES 模块,但 Oxc transformer 对命名空间提供了部分支持。
不支持使用 var 或 let 导出变量
不支持使用 var 或 let 导出变量。
namespace Foo {
export let bar = 1;
}
console.log(Foo.bar);一种解决方法是使用 const。如果你需要变量可变,请使用带内部可变性的对象:
namespace Foo {
export const bar = { value: 1 };
}
console.log(Foo.bar.value);命名空间不会在同名命名空间之间共享作用域
namespace Foo {
export const bar = 1;
}
namespace Foo {
export const baz = bar;
}let foo;
(function (_Foo) {
const bar = (_Foo.bar = 1);
})(Foo || (Foo = {}));
(function (_Foo2) {
const baz = (_Foo2.baz = bar);
})(Foo || (Foo = {}));var Foo;
(function (Foo) {
Foo.bar = 1;
})(Foo || (Foo = {}));
(function (Foo) {
Foo.baz = Foo.bar;
})(Foo || (Foo = {}));在这个示例中,TypeScript 编译器输出中第二个命名空间里的 bar 引用指向第一个命名空间中的 bar 变量,但 Oxc transformer 的输出中不是这样。
一种解决方法是通过命名空间对象显式引用:
namespace Foo {
export const bar = 1;
}
namespace Foo {
export const baz = Foo.bar;
}