Timmmm
Timmmm

Reputation: 96938

How to get typed $data with class based Vue component

I have a component something like this:

interface Data {
  currentDirectory: string;
}

@Component({
})
export default class TileMemory extends Vue {

  public data(): Data {
    return {
      currentDirectory: '/',
    };
  }

  public clearDirectory() {
    this.$data.currentDirectory = '';
  }
}

This appears to work, however this.$data.currentDirectory has the type any, not string even though I annotated the return type of data(). I've tried various things - putting data() in @Component({}) instead (where should it go? nobody seems to know), using this.currentDirectory instead (does not compile).

Is there a way to get proper types for the data object?

Upvotes: 3

Views: 115

Answers (2)

tony19
tony19

Reputation: 138596

Note that $data is a Record<string, any>, so its property values will always be type any.

Assuming you're using vue-class-component (the default in a Vue CLI project), you don't need to declare the data() method. You could simply declare initial data as class properties like this:

import { Component, Vue } from 'vue-property-decorator';

@Component
export default class TileMemory extends Vue {
  currentDirectory = '/'

  public clearDirectory() {
    this.currentDirectory = ''
  }
}

If for some reason you prefer using the data() method with the Data interface, you could achieve type safety with type assertions:

export default class TileMemory extends Vue {
  //...

  public clearDirectory() {
    (this.$data as Data).currentDirectory = ''
  }
}

...or using a getter (convenient if you have many usages):

export default class TileMemory extends Vue {
  //...

  get $$data() {
    return this.$data as Data
  }

  public clearDirectory() {
    this.$$data.currentDirectory = ''
  }
}

Upvotes: 1

Robson Oliveira
Robson Oliveira

Reputation: 497

Try to change the function data to a computed property, something like this:

interface Data {
  currentDirectory: string;
}

@Component({
})
export default class TileMemory extends Vue {

  get data(): Data {
    return {
      currentDirectory: '/',
    };
  }

  public clearDirectory() {
    this.data.currentDirectory = '';
  }
}

Upvotes: 1

Related Questions