Transform ID:Documentation Index
Fetch the complete documentation index at: https://docs.refactron.dev/llms.txt
Use this file to discover all available pages before exploring further.
object_assign_to_spread
Language: TypeScript
What it does
RewritesObject.assign({}, a, b, { x: 1 }) to the equivalent spread object literal { ...a, ...b, x: 1 }. Only safe when the first argument is an object literal — Object.assign(target, ...) against a mutable target has return-value and mutation semantics that a spread expression does not preserve.
Source-merging rules:
- Properties of the first-arg literal contribute first (preserving their original order).
- Each subsequent argument that is itself an object literal inlines its properties directly (avoiding redundant
{ ...{x:1} }). - Any other expression becomes a
...exprspread.
() => Object.assign({}, a)), the output is paren-wrapped (() => ({ ...a })) to disambiguate from a block statement. Transform at src/transform/transforms/typescript/object-assign-to-spread.ts.
Detector pattern
The detector atsrc/analyze/detectors/typescript/object-assign-empty.ts matches ts-morph CallExpression nodes whose callee is exactly Object.assign (not MyObject.assign, not a bare assign(…)) and whose first argument is an ObjectLiteralExpression.
Preconditions
non_es2018— refuses when the resolved tsconfigtargetpredates ES2018. Object spread is an ES2018 syntax addition.non_literal_target— refuses when the first arg is not anObjectLiteralExpression.Object.assign(existing, a)mutatesexistingand returns it; the spread form would silently lose that behaviour.spread_argument_present— refuses when any source uses spread-element syntax (Object.assign({}, ...sources)). The spread-object form{...sources}doesn’t iteratesources, so there is no 1:1 rewrite.
Before / after
Edge cases NOT handled (skip via precondition)
- Mutating-target form (
Object.assign(existing, a)) —non_literal_target; would change mutation and return-value semantics. - Spread-argument source (
Object.assign({}, ...sources)) —spread_argument_present; no equivalent spread-object form. - tsconfig
target< ES2018 —non_es2018; object spread is not in the runtime grammar.
The first-arg literal acts as the safety witness: it’s the only shape where the call has no observable mutation effect — the empty (or property-bearing) object is throwaway, and the merged result is what the call returns. Anything else and the rewrite would silently change semantics.