> ## 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.

# vue_set_delete_to_assignment

> Replace Vue.set / Vue.delete (and this.$set / this.$delete) with plain assignment / delete (Vue 3).

**Transform ID:** `vue_set_delete_to_assignment`
**Language:** TypeScript

## What it does

Rewrites Vue 2 reactivity helpers to plain JavaScript:

* `Vue.set(obj, key, value)` → `obj[key] = value` (or `obj.key = value` for ident-shaped string keys)
* `Vue.delete(obj, key)` → `delete obj[key]` (or `delete obj.key`)
* `this.$set(obj, key, value)` → `obj[key] = value`
* `this.$delete(obj, key)` → `delete obj[key]`

Key form selection: a string-literal key that is a valid JS identifier AND not a reserved word (`class`, `interface`, `for`, …) is rendered as dot notation. Anything else (spaces, digit-first, reserved words, numeric literals, identifier expressions, computed keys) uses bracket notation. Transform at `src/transform/transforms/typescript/vue-set-delete.ts`.

## Detector pattern

The detector at `src/analyze/detectors/typescript/vue-set-delete.ts` matches `CallExpression` whose callee is `Vue.set` / `Vue.delete` (identifier + property access) or `this.$set` / `this.$delete` (this-expression + property access).

## Preconditions

1. **`vue_sfc_not_supported`** — refuses any `.vue` Single-File-Component file. SFC support requires a dedicated parser and is deferred to v0.4. `.js` / `.ts` files only.
2. **`wrong_arity`** — refuses when the call doesn't have the expected argument count (3 for `set`, 2 for `delete`).
3. **`delete_in_expression_context`** — refuses `Vue.delete(...)` (and `this.$delete(...)`) anywhere its return value is consumed. `Vue.delete` returns `undefined`; the native `delete` operator returns a boolean — silently switching values would change semantics. `Vue.set` is safe in expression position because `obj.k = v` evaluates to `v`, which is what `Vue.set` already returns; the rewritten form is paren-wrapped for precedence.

## Before / after

<CodeGroup>
  ```ts before.ts theme={null}
  const obj: Record<string, number> = {};

  Vue.set(obj, 'foo', 1);
  Vue.set(obj, 'foo bar', 2);
  Vue.delete(obj, 'foo');

  class C {
    items: unknown[] = [];
    update(idx: number, item: unknown): void {
      this.$set(this.items, idx, item);
    }
  }
  ```

  ```ts after.ts theme={null}
  const obj: Record<string, number> = {};

  obj.foo = 1;
  obj["foo bar"] = 2;
  delete obj.foo;

  class C {
    items: unknown[] = [];
    update(idx: number, item: unknown): void {
      this.items[idx] = item;
    }
  }
  ```
</CodeGroup>

Reserved-word string keys (`class`, `interface`, …) preserve bracket notation:

```ts theme={null}
Vue.set(obj, 'class', 'x');
// → obj["class"] = "x"
```

## Edge cases NOT handled (skip via precondition)

* `.vue` Single-File-Component files — `vue_sfc_not_supported`; v0.4 follow-up.
* `Vue.delete(...)` used in expression position (`const r = Vue.delete(obj, k)`, function-call args, binary operands) — `delete_in_expression_context`; return-value semantics differ.
* Wrong arity (`Vue.set(a, b)`, `Vue.delete(a)`) — `wrong_arity`.

<Note>
  **Vue 2 reactivity caveat (ships in the suggestion text, not as a precondition):** Vue 2's `Object.defineProperty`-based reactivity requires `Vue.set` to add NEW reactive keys; direct assignment is not reactive for new keys on a Vue 2 instance. Vue 3 (Proxy-based) makes direct assignment reactive, so the rewrite is semantically equivalent. v0.2.3 assumes Vue 3 — on Vue 2 codebases, exclude this transform via `--exclude vue_set_delete_to_assignment` or your `.refactronrc.json`. A `vueMajorVersion` config key is a v0.4 follow-up.
</Note>
