How do I use Vue3 + TypeScript v-model on textfield? "ERROR: Invalid assignment target"

Full Error:

[plugin:vite:vue] Transform failed with 1 error:
ERROR: Invalid assignment target


Invalid assignment target
31 |        ? (_openBlock(), _createElementBlock("div", _hoisted_2, [
32 |            _withDirectives(_createElementVNode("textarea", {
33 |              "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (($ = $event))
   |                                                                           ^
34 |            }, null, 512 /* NEED_PATCH */), [
35 |              [

Here is the App.vue:

<script setup lang="ts">
import { ref } from 'vue'

interface Thing {
  description: string

const np = ref<Thing>({
  description: 'asdf asdf asdf',

  {{ np?.description }}
  <br />
  <textarea v-model.trim="np?.description"></textarea>

HERE is a Full recreation of the error:

Any help here is appreciated <3
This problem is rather confounding.

>Solution :

You can’t use dual-binding (v-model) with optional chaining (np?.description). Dual binding means getter & setter. What do you expect the setter to set when np is falsey? I know you wrapped it in v-if but optional chaining tells v-model the target object structure is possibly undefined, and that’s an invalid assignment target.

One way to go about it is create a description computed, where you specify how to set np.description when the current value of np allows it:

const description = computed({
  get() {
    return np.value?.description || ''
  set(description) {
    if (np.value) {
      np.value = { description }

See it working here:

The above is a generic alternative (when you actually need to use optional chaining with v-model).
A simpler alternative, in your case, is not using optional chaining with v-model, possible because you wrapped the <textarea> in v-if="np":
replace v-model.trim="np?.description" with v-model.trim="np.description".

It will work.

Leave a Reply