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) {}
}// 省略辅助函数
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,
);// 省略辅助函数
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) {}
}// 省略辅助函数
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 中使用 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); // 声明 source map(如果启用了 sourcemap)注意事项
隔离模块
由于 Oxc transformer 独立转换每个文件,某些 TypeScript 功能不受支持。 为了避免使用不支持的功能,您应该在 tsconfig.json 文件中启用 isolatedModules 选项。
部分命名空间支持
TypeScript 有一个称为命名空间的旧功能。虽然建议新项目使用 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 = {}));在此示例中,第二个命名空间中的 bar 引用对于 TypeScript 编译器输出指向第一个命名空间中的 bar 变量,但对于 Oxc transformer 输出则不然。
解决方法是通过命名空间对象显式引用:
namespace Foo {
export const bar = 1;
}
namespace Foo {
export const baz = Foo.bar;
}