Search code examples
typescriptvue.js

VueJS/Typescript - define reactive values in typescript class


I've came across the idea, defining ref() or computed values etc. in an external class for having a cleaner code structure and less overloaded .vue file.

For Example i have a test.ts file like this.

import { ref, computed } from "vue";
import type { Ref, ComputedRef } from "vue";

export class Test {
    public refValue: Ref<number> = ref(0)
    public compValue: ComputedRef<string> = computed(() => {
        if (this.refValue.value === 0) return 'No Value given'
        else return `Value is ${this.refValue.value}`
    })

    constructor() {}

    public init() {
        this.refValue.value = 10
    }

}

And a Test.vue file like this

<template>
  <div v-if="test">
    <span>{{ test.refValue }}</span>
    <span>{{ test.compValue }}</span>
  </div>
<template>
<script setup lang="ts">
import { Test } from './Test.ts'
import { onMounted } from 'vue'

const test = ref<Test | null>(null)

onMounted(() => {
  test.value = new Test()
  test.value.init()
})
</script>

I've tried this example and the .ts file just deletes the ref() assigned to the refValue and assigns the value to it.

( refValue = 0 )

In this case at the init() there would be an Type error because there is no 'value' in 0.

So here my question: Is this possible doing it this way and when it is, what am i doing wrong?

( Source : VueJS.org )


Solution

  • See Vue Docs - ref() will unwrap nested refs. It means:

    ref({
      refValue: ref(0),
      __proto__: Test,
    })
    
    // equals to
    ref({
      refValue: 0,
      __proto__: Test,
    })
    

    So this.refValue = 0.

    You can use shallowRef to avoid this behavior.

    demo