# Vue Computed Get Set: How to Create Writable Computed Properties in Vue 3

> Learn how to create writable computed properties in Vue 3 using the object syntax with get and set functions. Master Vue computed get set for dynamic data management.

- Repository: [Vue/core](https://github.com/vuejs/core)
- Tags: how-to-guide
- Published: 2026-02-21

---

**Use the object syntax `computed({ get: () => ..., set: (val) => ... })` to create a writable computed ref that can be read and assigned to like a standard ref.**

When working with the Composition API in Vue 3, you often need derived state that also supports two-way binding. The **vue computed get set** pattern allows you to define both a getter for deriving values and a setter for propagating changes back to source state. Internally, the Vue core repository (`vuejs/core`) implements this through the `computed()` function in [`packages/reactivity/src/computed.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/src/computed.ts), which creates a `WritableComputedRefImpl` instance when it detects an object with `get` and `set` methods.

## Understanding the Vue Computed Get Set Syntax

By default, `computed()` accepts a single getter function and returns a readonly ref. To enable the **vue computed get set** behavior, you pass an object containing both `get` and `set` properties:

```typescript
import { computed, ref } from 'vue'

const count = ref(0)

const doubled = computed({
  get: () => count.value * 2,
  set: (val: number) => {
    count.value = val / 2
  }
})

```

In this pattern, `doubled.value` reads from the getter, while assigning to `doubled.value = 10` invokes the setter, which updates the underlying `count` ref.

### How Writable Computed Works Under the Hood

When you provide an object with `get` and `set`, the `computed()` factory in [`packages/reactivity/src/computed.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/src/computed.ts) instantiates a `WritableComputedRefImpl` class. This implementation:

1. Wraps the getter in a `ReactiveEffect` to track reactive dependencies
2. Stores the setter function for later invocation when the ref receives a new value
3. Exposes the standard `Ref` interface with `.value` property, allowing seamless integration with the template proxy system

The `ReactiveEffect` ensures that when dependencies inside the getter change, the computed value invalidates its cache and re-evaluates on the next access, maintaining Vue's efficient reactivity guarantees.

## Vue Computed Get Set Implementation Details

The architectural flow for a writable computed property follows these specific steps as implemented in the Vue core:

| Step | Implementation Detail | Source Location |
|------|----------------------|-----------------|
| **1. Object Detection** | `computed()` checks if the argument is an object with `get` and `set` methods, distinguishing it from a simple getter function. | [`packages/reactivity/src/computed.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/src/computed.ts) |
| **2. Effect Creation** | The getter is wrapped in a `ReactiveEffect` that tracks reactive dependencies accessed during execution. | [`packages/reactivity/src/computed.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/src/computed.ts) |
| **3. Setter Storage** | The provided `set` function is stored on the `WritableComputedRefImpl` instance for invocation during write operations. | [`packages/reactivity/src/computed.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/src/computed.ts) |
| **4. Ref Interface** | The instance implements the `Ref` interface, exposing a `.value` property that triggers getter/setter logic appropriately. | [`packages/reactivity/__tests__/computed.spec.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/__tests__/computed.spec.ts) |

This architecture ensures that **vue computed get set** properties remain fully reactive while providing controlled mutation capabilities through the setter interface.

## Practical Vue Computed Get Set Example

Here is a complete, runnable example demonstrating a writable computed property that synchronizes a full name with separate first and last name refs:

```typescript
import { ref, computed, defineComponent } from 'vue'

export default defineComponent({
  setup() {
    // Source reactive state
    const firstName = ref('Ada')
    const lastName = ref('Lovelace')

    // Writable computed with get and set
    const fullName = computed({
      get() {
        // Derive full name from parts
        return `${firstName.value} ${lastName.value}`
      },
      set(newValue: string) {
        // Parse and update source refs
        const [first, ...rest] = newValue.split(' ')
        firstName.value = first
        lastName.value = rest.join(' ')
      }
    })

    // Reading the computed
    console.log(fullName.value) // "Ada Lovelace"

    // Writing to the computed triggers the setter
    fullName.value = 'Grace Hopper'
    console.log(firstName.value) // "Grace"
    console.log(lastName.value)  // "Hopper"

    return { firstName, lastName, fullName }
  }
})

```

### Template Usage with v-model

The **vue computed get set** pattern enables seamless two-way binding in templates:

```html
<template>
  <div>
    <p>First: {{ firstName }}</p>
    <p>Last: {{ lastName }}</p>
    
    <!-- Two-way binding works because fullName has a setter -->
    <input v-model="fullName" placeholder="Enter full name" />
  </div>
</template>

```

When the user types in the input, `v-model` automatically invokes the setter, which parses the string and updates the underlying `firstName` and `lastName` refs.

## Key Source Files for Vue Computed Get Set

Understanding the implementation requires examining these specific files in the `vuejs/core` repository:

| File | Purpose |
|------|---------|
| [`packages/reactivity/src/computed.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/src/computed.ts) | Core implementation of `computed()`, including `WritableComputedRefImpl` class and `ReactiveEffect` integration for getters. |
| [`packages/reactivity/__tests__/computed.spec.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/__tests__/computed.spec.ts) | Comprehensive test suite validating writable computed behavior, including setter invocation and reactivity edge cases. |
| [`packages/reactivity/__benchmarks__/computed.bench.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/__benchmarks__/computed.bench.ts) | Performance benchmarks demonstrating the efficiency of the computed effect scheduling system. |

These files demonstrate how Vue maintains reactivity performance while supporting the **vue computed get set** pattern through careful effect tracking and cache invalidation.

## Summary

- **Vue computed get set** properties are created by passing an object with `get` and `set` methods to `computed()` in the Composition API.
- The implementation resides in [`packages/reactivity/src/computed.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/src/computed.ts), which creates a `WritableComputedRefImpl` instance wrapping the getter in a `ReactiveEffect`.
- Writable computed refs expose the standard `.value` interface, enabling both reading (via getter) and writing (via setter) while maintaining full reactivity.
- This pattern supports two-way binding with `v-model` in templates, allowing computed properties to serve as bridges between UI inputs and source state.

## Frequently Asked Questions

### Can you use vue computed get set with the Options API?

Yes, the Options API supports writable computed properties through the same `get` and `set` syntax within the `computed` option of a component. While the syntax differs from the Composition API's `computed()` function, the underlying reactivity system in [`packages/reactivity/src/computed.ts`](https://github.com/vuejs/core/blob/main/packages/reactivity/src/computed.ts) handles both approaches identically.

### What happens if you assign to a computed without a setter?

If you attempt to assign to a computed property that was created with only a getter function (the default), Vue will throw a runtime warning stating "Write operation failed: computed value is readonly." This protection ensures that derived state cannot be accidentally mutated without an explicit setter defining the mutation logic.

### How does Vue track dependencies in a writable computed?

Vue wraps the `get` function in a `ReactiveEffect` instance when creating the computed ref. During execution of the getter, any accessed reactive values (refs or reactive objects) are automatically tracked as dependencies. When those dependencies change, the effect triggers, invalidating the computed cache and scheduling a re-evaluation for the next read operation.

### Is there a performance difference between readonly and writable computed?

There is no significant performance difference between readonly and writable computed properties in Vue 3. Both use the same `ReactiveEffect` mechanism for dependency tracking and caching. The only additional overhead for writable computed is the storage of the setter function reference, which is negligible compared to the cost of effect scheduling and re-evaluation.