Reputation: 109
I'm using the options api and when attempting to access a property of the Vue data object in a computed property I get an error in the typechecking.
Property 'quantity' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, { item: unknown; total: unknown; menuItemCategories: any; }, Readonly<Record<never, any>>>'
The property does exist since the page is able to load and display rendered template correctly using the computed property - only the type checker complains.
The component code (simplified for length):
import Vue from "vue";
export default Vue.extend({
data() {
quantity: 1,
},
computed: {
total() {
return this.item.price * this.quantity;
}
},
});
Edit
I've been able to work around the issue by using the data
property as an object.
This does create some issues though since it is best practice to use data
as a function which returns an object. The same issue applies to asyncData
.
Further trial and error has shown I'm able to access the data
function properties through the methods
property. However if I use the mapGetters
helper from vuex it throws the same type error as computed properties.
The methods
are also not available in the CombinedVueInstance
type inside computed properties.
tsconfig.json
// tsconfig.json
{
"compilerOptions": {
"target": "es2018",
"module": "esnext",
"moduleResolution": "node",
"lib": [
"esnext",
"esnext.asynciterable",
"dom"
],
"esModuleInterop": true,
"allowJs": true,
"sourceMap": true,
"strict": true,
"noEmit": true,
"baseUrl": "./src",
"paths": {
"~/*": [
"./*"
],
"@/*": [
"./*"
]
},
"types": [
"@types/node",
"@nuxt/types",
"@nuxtjs/axios"
]
},
"exclude": [
"node_modules"
]
}
vue-shim.d.ts
declare module "*.vue" {
import Vue from 'vue'
export default Vue
}
Upvotes: 1
Views: 6745
Reputation: 109
Type checking with the Nuxt Typescript has some strange behaviors caused by it not being able to infer all the types correctly. This is further compounded by using Vuex vanilla and helper functions.
To get complete type information with minimal boilerplate it is best to use vue-class-component and vue-property-decorator as shown in the Nuxt Typescript docs - Components (See Class API), along with the class based vuex-module-decorators See Nuxt Typescript Docs - Store.
However, to answer the original question for solving this while still using the Options API - you must declare the return type for all functions in computed
and methods
; and coerce the Vuex helper functions as needed.
Unfortunately we still don't get correct type checking for asyncData
so we must duplicate our code a across data
and asyncData
functions.
import Vue from "vue";
import { mapGetters } from "vuex";
export default Vue.extend({
// Default component data - supports type checking
data() {
return {
quantity: 1,
}
},
// Actual component data - sourced from api
async asyncData() {
const theAwaitedQuantity = // ... some await methods and promises from a backend api
return {
quantity: theAwaitedQuantity,
}
},
computed: {
...mapGetters(["item"]),
total(): number {
// mapped properties from helper functions must have their types coerced.
return (this.item as ItemType).price * this.quantity;
}
},
methods: {
someMethod(): string {
return "methods also need their return type defined";
}
}
});
Also see this related issue: Property 'XXX' does not exist on type 'CombinedVueInstance<Vue, {}, {}, {}, Readonly<Record<never, any>>>'
Upvotes: 7