Set data Type in Vue data object with Typescript
Typescriptvue.jsVuejs2Typescript 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);
});
},
});