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??
6 Answers
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>() };
}, 2 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: [] }; },
}) 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.
I found another method that is more close to the typical syntax, while keeping the code short.
data() { return new class { players: Player[] = [] }();
}, 1 Type assertion using the '<>' syntax is forbidden. Use the 'as' syntax instead.
It will look like this:
players: [] as Player[] 2 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); }); }, });