Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions napi/transform/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,41 @@ export interface TypeScriptOptions {
onlyRemoveTypeImports?: boolean
allowNamespaces?: boolean
allowDeclareFields?: boolean
/**
* When enabled, class fields without initializers are removed.
*
* For example:
* ```ts
* class Foo {
* x: number;
* y: number = 0;
* }
* ```
* // transform into
* ```js
* class Foo {
* x: number;
* }
* ```
*
* The option is used to align with the behavior of TypeScript's `useDefineForClassFields: false` option.
* When you want to enable this, you also need to set [`crate::CompilerAssumptions::set_public_class_fields`]
* to `true`. The `set_public_class_fields: true` + `remove_class_fields_without_initializer: true` is
* equivalent to `useDefineForClassFields: false` in TypeScript.
*
* When `set_public_class_fields` is true and class-properties plugin is enabled, the above example transforms into:
*
* ```js
* class Foo {
* constructor() {
* this.y = 0;
* }
* }
* ```
*
* Defaults to `false`.
*/
removeClassFieldsWithoutInitializer?: boolean
/**
* Also generate a `.d.ts` declaration file for TypeScript files.
*
Expand Down
38 changes: 36 additions & 2 deletions napi/transform/src/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,39 @@ pub struct TypeScriptOptions {
pub only_remove_type_imports: Option<bool>,
pub allow_namespaces: Option<bool>,
pub allow_declare_fields: Option<bool>,
/// When enabled, class fields without initializers are removed.
///
/// For example:
/// ```ts
/// class Foo {
/// x: number;
/// y: number = 0;
/// }
/// ```
/// // transform into
/// ```js
/// class Foo {
/// x: number;
/// }
/// ```
///
/// The option is used to align with the behavior of TypeScript's `useDefineForClassFields: false` option.
/// When you want to enable this, you also need to set [`crate::CompilerAssumptions::set_public_class_fields`]
/// to `true`. The `set_public_class_fields: true` + `remove_class_fields_without_initializer: true` is
/// equivalent to `useDefineForClassFields: false` in TypeScript.
///
/// When `set_public_class_fields` is true and class-properties plugin is enabled, the above example transforms into:
///
/// ```js
/// class Foo {
/// constructor() {
/// this.y = 0;
/// }
/// }
/// ```
///
/// Defaults to `false`.
pub remove_class_fields_without_initializer: Option<bool>,
/// Also generate a `.d.ts` declaration file for TypeScript files.
///
/// The source file must be compliant with all
Expand Down Expand Up @@ -252,8 +285,9 @@ impl From<TypeScriptOptions> for oxc::transformer::TypeScriptOptions {
allow_namespaces: options.allow_namespaces.unwrap_or(ops.allow_namespaces),
allow_declare_fields: options.allow_declare_fields.unwrap_or(ops.allow_declare_fields),
optimize_const_enums: false,
// TODO: Implement
remove_class_fields_without_initializer: false,
remove_class_fields_without_initializer: options
.remove_class_fields_without_initializer
.unwrap_or(ops.remove_class_fields_without_initializer),
rewrite_import_extensions: options.rewrite_import_extensions.and_then(|value| {
match value {
Either::A(v) => {
Expand Down
58 changes: 58 additions & 0 deletions napi/transform/test/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,61 @@ describe('worker', () => {
expect(code).toBe(0);
});
});

describe('typescript', () => {
describe('options', () => {
test('removeClassFieldsWithoutInitializer', () => {
const code = `
class Foo {
a: number;
b: number = 1;
}
`;
const ret = transform('test.ts', code, {
typescript: {
removeClassFieldsWithoutInitializer: true,
},
});
expect(ret.code).toMatchInlineSnapshot(`
"class Foo {
b = 1;
}
"
`);
});

test('align `useDefineForClassFields: false`', () => {
const code = `
class Foo {
a: number;
b: number = 1;
@dec
c: number;
}
`;
const ret = transform('test.ts', code, {
assumptions: {
setPublicClassFields: true,
},
target: 'es2020',
typescript: {
removeClassFieldsWithoutInitializer: true,
},
decorator: {
legacy: true,
},
});
expect(ret.code).toMatchInlineSnapshot(`
"import _decorate from "@oxc-project/runtime/helpers/decorate";
class Foo {
constructor() {
this.b = 1;
this.c = void 0;
}
}
_decorate([dec], Foo.prototype, "c", void 0);
"
`);
});
});
});
Loading