diff --git a/crates/oxc_ast/src/ast_impl/js.rs b/crates/oxc_ast/src/ast_impl/js.rs index a67593e7e..8b5032b3b 100644 --- a/crates/oxc_ast/src/ast_impl/js.rs +++ b/crates/oxc_ast/src/ast_impl/js.rs @@ -626,6 +626,10 @@ impl<'a> AssignmentTarget<'a> { pub fn get_expression(&self) -> Option<&Expression<'a>> { self.as_simple_assignment_target().and_then(SimpleAssignmentTarget::get_expression) } + + pub fn get_expression_mut(&mut self) -> Option<&mut Expression<'a>> { + self.as_simple_assignment_target_mut().and_then(SimpleAssignmentTarget::get_expression_mut) + } } impl<'a> SimpleAssignmentTarget<'a> { diff --git a/crates/oxc_transformer/src/typescript/annotations.rs b/crates/oxc_transformer/src/typescript/annotations.rs index 9e42a1021..c6a4fbab4 100644 --- a/crates/oxc_transformer/src/typescript/annotations.rs +++ b/crates/oxc_transformer/src/typescript/annotations.rs @@ -250,10 +250,14 @@ impl<'a> TypeScriptAnnotations<'a> { } pub fn transform_assignment_target(&mut self, target: &mut AssignmentTarget<'a>) { - if let Some(expr) = target.get_expression() { - if let Some(member_expr) = expr.get_inner_expression().as_member_expression() { - // SAFETY: `ast.copy` is unsound! We need to fix. - *target = AssignmentTarget::from(unsafe { self.ctx.ast.copy(member_expr) }); + if let Some(expr) = target.get_expression_mut() { + let inner_expr = expr.get_inner_expression_mut(); + if inner_expr.is_member_expression() { + let inner_expr = self.ctx.ast.move_expression(inner_expr); + let Ok(member_expr) = MemberExpression::try_from(inner_expr) else { + unreachable!(); + }; + *target = AssignmentTarget::from(member_expr); } } }