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
13 changes: 8 additions & 5 deletions crates/oxc_transformer/src/typescript/annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub struct TypeScriptAnnotations<'a, 'ctx> {
has_jsx_fragment: bool,
jsx_element_import_name: String,
jsx_fragment_import_name: String,
remove_class_fields_without_initializer: bool,
}

impl<'a, 'ctx> TypeScriptAnnotations<'a, 'ctx> {
Expand All @@ -52,6 +53,8 @@ impl<'a, 'ctx> TypeScriptAnnotations<'a, 'ctx> {
has_jsx_fragment: false,
jsx_element_import_name,
jsx_fragment_import_name,
remove_class_fields_without_initializer: options
.remove_class_fields_without_initializer,
}
}
}
Expand Down Expand Up @@ -227,11 +230,11 @@ impl<'a> Traverse<'a> for TypeScriptAnnotations<'a, '_> {
&& !method.value.is_typescript_syntax()
}
ClassElement::PropertyDefinition(prop) => {
if prop.declare {
false
} else {
matches!(prop.r#type, PropertyDefinitionType::PropertyDefinition)
}
matches!(prop.r#type, PropertyDefinitionType::PropertyDefinition)
&& !prop.declare
&& !(self.remove_class_fields_without_initializer
&& prop.value.is_none()
&& prop.decorators.is_empty())
}
ClassElement::AccessorProperty(prop) => {
matches!(prop.r#type, AccessorPropertyType::AccessorProperty)
Expand Down
36 changes: 36 additions & 0 deletions crates/oxc_transformer/src/typescript/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,41 @@ pub struct TypeScriptOptions {
#[serde(default = "default_as_true")]
pub allow_declare_fields: 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`.
#[serde(default)]
pub remove_class_fields_without_initializer: bool,

/// Unused.
pub optimize_const_enums: bool,

Expand All @@ -66,6 +101,7 @@ impl Default for TypeScriptOptions {
only_remove_type_imports: false,
allow_namespaces: default_as_true(),
allow_declare_fields: default_as_true(),
remove_class_fields_without_initializer: false,
optimize_const_enums: false,
rewrite_import_extensions: None,
}
Expand Down
2 changes: 2 additions & 0 deletions napi/transform/src/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ 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,
rewrite_import_extensions: options.rewrite_import_extensions.and_then(|value| {
match value {
Either::A(v) => {
Expand Down
6 changes: 3 additions & 3 deletions tasks/transform_conformance/snapshots/oxc.snap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
commit: 578ac4df

Passed: 150/246
Passed: 153/249

# All Passed:
* babel-plugin-transform-class-static-block
Expand Down Expand Up @@ -44,7 +44,7 @@ after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(6), R
rebuilt : SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(6), ReferenceId(10)]


# babel-plugin-transform-typescript (4/20)
# babel-plugin-transform-typescript (6/22)
* class-property-definition/input.ts
Unresolved references mismatch:
after transform: ["const"]
Expand Down Expand Up @@ -424,7 +424,7 @@ after transform: SymbolId(4): ScopeId(1)
rebuilt : SymbolId(5): ScopeId(4)


# legacy-decorators (2/71)
# legacy-decorators (3/72)
* oxc/metadata/bound-type-reference/input.ts
Symbol reference IDs mismatch for "BoundTypeReference":
after transform: SymbolId(0): [ReferenceId(1), ReferenceId(3), ReferenceId(4), ReferenceId(5), ReferenceId(6)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Cls {
x: number;
y = 1;
@dce
z: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": [["transform-typescript", { "removeClassFieldsWithoutInitializer": true }]]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Cls {
y = 1;
@dce
z;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Cls {
x: number;
y = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"assumptions": {
"setPublicClassFields": true
},
"plugins": [
"transform-class-properties",
[
"transform-typescript",
{
"removeClassFieldsWithoutInitializer": true
}
]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Cls {
constructor() {
this.y = 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Cls {
x: number;
y = 1;
@dce
z: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"plugins": [
"transform-legacy-decorator",
[
"transform-typescript",
{
"removeClassFieldsWithoutInitializer": true
}
]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Cls {
y = 1;
z;
}
babelHelpers.decorate([dce], Cls.prototype, "z", void 0);
Loading