1
votes

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
}
1
data should be a function which returns an objectLawrence Cherone
@LawrenceCherone I'm aware - I've stated its a workaround to get the typechecking to behave. Doesn't solve the issue.0x0byte
@LawrenceCherone I stated that in the very next sentence - please read carefully.0x0byte
@LawrenceCherone I took my own advice and tested using an arrow function instead of a basic data() function. It solved the issue. Thank you for the help and sorry if I came off as rude.0x0byte
I answered this question on stackoverflow.com/questions/56002310/…. I hope it will help.Serkan KONAKCI

1 Answers

3
votes

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>>>'