Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specify non-reactive instance property in Vue.js using TypeScript?

I am migrating my Vue.js components to TypeScript. Following the guide, I tried to use Vue.extend() for my component. My component is:

import Vue from 'vue';

const Component = Vue.extend({
  // type inference enabled

  created() {
    // `y` is non-reactive property
    this.y = 20; // TYPESCRIPT THROWS ERROR
  }

  data() {
     return {
        // x is reactive property
        x: 10
     };
  }

});

In above example, I have property x which is reactive and y as non-reactive property. However, I just cannot get type inference working for property y due the way augmentation works in TypeScript.

I cannot use simple object export for defining my component as it starts throwing a type error for both y and x.

For, now I am sticking to keeping this file as JS or move my code vue-class-component which enable me to handle this. However, I am reluctant to move to vue-class-component as it is a code at a library level.

Any solution to how I can make TypeScript happy?

like image 507
Harshal Patil Avatar asked Jan 03 '18 04:01

Harshal Patil


People also ask

Does vue2 support TypeScript?

You should also be familiar with Vue, vue-loader, and webpack. Vue 2 already has good support for TypeScript, and the recently published Vue 2.7 backported a lot of useful features from Vue 3, like composition API, <script setup> , and defineComponent , further improving the developer experience of TypeScript in Vue.

What is defineComponent in vue3?

defineComponent({ setup: function , name: 'some name' }); As you see, all these cases are responsible for different scenarios, yet the return type is always the same: a defineComponent interface with all the types you need to apply for the props, data and the other settings that are needed for the component.

How do I make my house reactive in Vue?

The Reactive Method #observable() in Vue 2.6, can be useful when we're trying to create an object all of whose properties are reactive (such as the data object in the Options API). Under the hood, the data object in the Options API uses this method to make all of the properties in it reactive.


2 Answers

A simplest solution would be something like this:

  data() {
     return {
        // x is reactive property
        x: 10
     } as any as { x: number; y: number };
  }

however that requires you to explicitly define all properties of data.


Alternatively, you can do it with the following helper:

function withNonReactive<TData>(data: TData) {
    return <TNonReactive>() => data as TData & TNonReactive;
}

Like this:

  data() {
     return withNonReactive({
        // x is reactive property
        x: 10
     })<{
        // non-reactive properties go here
        y: number
     }>();
  }
like image 161
Andrey Shchekin Avatar answered Oct 22 '22 21:10

Andrey Shchekin


One way to get rid of TypeScript errors this is by defining the following property:

data() {
    return {
       nonReactive: {} as any
    }
}

and then just add your non-reactive properties to this object in created().

created() {
    this.nonReactive.foo = {}
}

Another method I haven't really explored would be to create a typescript shim file for your component.

like image 41
gardarh Avatar answered Oct 22 '22 21:10

gardarh