1

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
}
5
  • data should be a function which returns an object Commented Jun 6, 2020 at 20:16
  • @LawrenceCherone I'm aware - I've stated its a workaround to get the typechecking to behave. Doesn't solve the issue. Commented Jun 6, 2020 at 20:17
  • @LawrenceCherone I stated that in the very next sentence - please read carefully. Commented Jun 6, 2020 at 20:23
  • @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. Commented Jun 6, 2020 at 20:25
  • I answered this question on stackoverflow.com/questions/56002310/…. I hope it will help. Commented Jul 23, 2021 at 21:43

1 Answer 1

7

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.