Set data Type in Vue data object with Typescript

Typescriptvue.jsVuejs2

Typescript Problem Overview


I'm currently using Vue.js with Typescript in a webpack project.

As indicated in the Recommended Configuration in my tsconfig.json I have:

"strict": true,

Inside one of my component i have:

declare interface Player {
    cod: string,
    param: string
  }

export default Vue.extend({
    name: 'basecomponent',
    data() {
      return {
        players: []
      };
    },
    created() 
      let self = this
      axios.get('fetch-data')
        .then((response) => {
          let res: Players[] = response.data;
          for(let i = 0; i < res.length; i++){
              self.players.push(res[i]);
          }
        })
        .catch((error: string) => {
          console.log(error);
       });
    },
 });

but when I try to compile i get:

 error TS2345: Argument of type 'Player' is not assignable to parameter of type 'never'.

Cause I believe players: [] has never[] type.

My question is: how can I infer type Vue data object properties??

Typescript Solutions


Solution 1 - Typescript

To add to Joshua's answer, you may want to declare the type of players inline so your code doesn't get too verbose as your data gets larger.

data() {
  return {
    players: [] as Player[]
  };
},

another option:

data() {
  return {
    players: new Array<Player>()
  };
},

Solution 2 - Typescript

This should work:

declare interface Player {
  cod: string,
  param: string
}

declare interface BaseComponentData {
  players: Player[]
}

export default Vue.extend({
  name: 'basecomponent',
  data(): BaseComponentData {
    return {
      players: []
    };
  },
})

Solution 3 - Typescript

Your data method has an undeclared return value.

If you supply one, TypeScript will know what to expect with players.

You just need to expand the data() { line.

e.g.:

data() {
  return {
    players: []
  };
},

needs to become:

data() : {
  players: Array<any>, // if possible, replace `any` with something more specific
} {
  return {
    players: []
  };
},

Tada! players is now of type Array of any.

Solution 4 - Typescript

I found another method that is more close to the typical syntax, while keeping the code short.

data() {
  return new class {
    players: Player[] = []
  }();
},

Solution 5 - Typescript

Type assertion using the '<>' syntax is forbidden. Use the 'as' syntax instead.

It will look like this:

players: [] as Player[]

Solution 6 - Typescript

In case anyone comes across this in the future, here is the answer that solved my problem. It is a little more "wordy", but it does the type inference properly everywhere within the Vue.extend() component definition:

interface Player {
  cod: string,
  param: string
}

// Any properties that are set in the `data()` return object should go here.
interface Data {
  players: Player[];
}

// Any methods that are set in the "methods()" should go here.
interface Methods {}

// Any properties that are set in the "computed()" should go here.
interface Computed {}

// Any component props should go here.
interface Props {}

export default Vue.extend<Data, Methods, Computed, Props>({
    name: 'basecomponent',
    data() {
      return {
        players: []
      };
    },
    // You probably will want to change this to the "mounted()" component lifecycle, as there are weird things that happen when you change the data within a "created()" lifecycle.
    created() {
      // This is not necessary.
      // let self = this
      // If you type the Axios.get() method like this, then the .data property is automatically typed.
      axios.get<Players[]>('fetch-data')
        .then(({ data }) => {
          // This is not necessary.
          // let res: Players[] = response.data;
          // for(let i = 0; i < data.length; i++){
          //     self.players.push(data[i]);
          // }
          this.players = data;
        })
        .catch((error: string) => {
          console.log(error);
       });
    },
 });

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPlasticView Question on Stackoverflow
Solution 1 - TypescriptMichael WilsonView Answer on Stackoverflow
Solution 2 - TypescriptOre4444View Answer on Stackoverflow
Solution 3 - TypescriptJoshua HansenView Answer on Stackoverflow
Solution 4 - TypescriptAhmadView Answer on Stackoverflow
Solution 5 - TypescriptИлья КаревView Answer on Stackoverflow
Solution 6 - Typescriptth3n3wguyView Answer on Stackoverflow