Search code examples
typescriptvue.jsvuejs3vue-composition-apivue-script-setup

How to use defineModel (in Vue 3.4) for uses other than inputs


The examples given for defineModel in the Vue docs all relate to uses for data inputs. I was wondering if this construct could also be used elsewhere, thus avoiding the somewhat cumbersome props/emit method of exchanging data between parent and child:

(app.vue):

<script setup lang="ts">
import { ref } from 'vue'
import MyComponent from './MyComponent.vue'
  
const title = ref('v-model argument example with array')
const array = ref([1,2,3,4,5]);
</script>

<template>
  <h1>{{ title }}</h1>
  <MyComponent  v-model:array = "array"  />
  <h2>Parent array: {{array}}</h2>
</template>

(myComponent.vue):

<script setup lang="ts">
const array  = defineModel('array')

function ShortenArray() {
  array.value = array.value.slice(1);
}
</script>

<template>
  <button @click="ShortenArray">Shorten Array</button>
  <p></p>
  child array: {{ array }}
</template>

This code runs as expected, but there is a typescript error Property 'slice' does not exist on type 'unknown' given for array.slice(), which I cannot resolve.

Vue playground here.


Solution

  • You need to add the type to your defineModel, in this case it can be an array of numbers :

    <script setup lang="ts">
    const array  = defineModel<Array<number>>('array')
    
    function ShortenArray() {
      array.value = array.value.slice(1);
    }
    </script>