15

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?

2
  • vue-class-component is an official Vue library. Commented Jan 3, 2018 at 4:43
  • I don't know much about TypeScript so my comment may be off, but why wouldn't you use computed values instead? Wouldn't that solve your reactive property case? Technically speaking it's still reactive, but it won't be on a static value. computed: { y: function () { return 20 }} Commented Jan 3, 2018 at 7:19

3 Answers 3

6

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
     }>();
  }
Sign up to request clarification or add additional context in comments.

Comments

3

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.

Comments

1

Solution without function wrapper

Vue.extend({
  data() {
    const reactive = {
      name: 'Jack Sparrow',
    }

    return reactive as typeof reactive & {
      nonReactiveProperty: string;
    }
  },
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.