[SOLVED] Methods not being attached/detected as part of TypeScript compilation

Issue

Sorry, this question is going to be a bit vague, mostly because I honestly don’t know where to go next. I followed this tutorial here (https://auth0.com/blog/how-to-make-secure-http-requests-with-vue-and-express/) and everything worked up to the nearly last entry. Now, I’m getting these errors:

ERROR in /home/aron/code/cx/client/src/views/EventSingle.vue(44,10):
44:10 Property 'getEventData' does not exist on type '{ name: string; data(): { event: {}; }; created(): void; methods: { getEventData(): Promise<void>; }; }'.
    42 |   },
    43 |   created() {
  > 44 |     this.getEventData(); // NEW - call getEventData() when the instance is created
       |          ^
    45 |   },
    46 | methods: {
    47 |   async getEventData() {
ERROR in /home/aron/code/cx/client/src/views/EventSingle.vue(49,36):
49:36 Property '$auth' does not exist on type '{ getEventData(): Promise<void>; }'.
    47 |   async getEventData() {
    48 |     // Get the access token from the auth wrapper
  > 49 |     const accessToken = await this.$auth.getTokenSilently()
       |                                    ^
    50 | 
    51 |     // Use the eventService to call the getEventSingle method
    52 |     EventService.getEventSingle(this.$route.params.id, accessToken)
ERROR in /home/aron/code/cx/client/src/views/EventSingle.vue(52,38):
52:38 Property '$route' does not exist on type '{ getEventData(): Promise<void>; }'.
    50 | 
    51 |     // Use the eventService to call the getEventSingle method
  > 52 |     EventService.getEventSingle(this.$route.params.id, accessToken)
       |                                      ^
    53 |     .then(
    54 |       (event => {
    55 |         this.$set(this, "event", event);
ERROR in /home/aron/code/cx/client/src/views/EventSingle.vue(55,14):
55:14 Property '$set' does not exist on type '{ getEventData(): Promise<void>; }'.
    53 |     .then(
    54 |       (event => {
  > 55 |         this.$set(this, "event", event);
       |              ^
    56 |       }).bind(this)
    57 |     );
    58 |   }

Here’s my tsconfig.json:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
"noImplicitAny": false,
    "allowSyntheticDefaultImports": true,
    "allowJs": true,
    "sourceMap": true,
    "baseUrl": ".",
    "resolveJsonModule": true,
    "types": [
      "webpack-env",
      "jest"
    ],
    "typeRoots": ["./@types", "./node_modules/@types"],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost","es2015", "es2016", "es2018.promise"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

I’m not incredibly familiar with TypeScript, Javascript, etc, and I’ve been poking around at various ways to solve this – https://blog.risingstack.com/auth0-vue-typescript-quickstart-docs/ and https://auth0.com/docs/quickstart/spa/vuejs/01-login.

My GUESS is that the Vue object prototype is not being extended with the Auth0 plug-in, and it’s something about the way the frameworks have changed since this tutorial was written. Any suggestions? Happy to paste in more info if it helps.

Thanks!


Thank you so much tony19! That solved three out of the four bugs – the new code looks like this:

import EventService from '../services/EventService.js';
import Vue from 'vue';
          
export default Vue.extend({
  name: 'EventSingle',
  data() {
    // NEW - initialize the event object
    return {
      event: {}
    }
  },
  created() {
    this.getEventData(); // NEW - call getEventData() when the instance is created
  },
  methods: {
    async getEventData() {
      // Get the access token from the auth wrapper
      const accessToken = await this.$auth.getTokenSilently()

      // Use the eventService to call the getEventSingle method
      EventService.getEventSingle(this.$route.params.id, accessToken)
      .then(
        (event => {
          this.$set(this, "event", event);
        }).bind(this)
      );
    }
  }
});

The only remaining bug is now here:

ERROR in /home/aron/code/cx/client/src/views/EventSingle.vue(51,38):
51:38 Property '$auth' does not exist on type 'CombinedVueInstance<Vue, { event: {}; }, { getEventData(): Promise<void>; }, unknown, Readonly<Record<never, any>>>'.
    49 |     async getEventData() {
    50 |       // Get the access token from the auth wrapper
  > 51 |       const accessToken = await this.$auth.getTokenSilently()
       |                                      ^
    52 | 
    53 |       // Use the eventService to call the getEventSingle method
    54 |       EventService.getEventSingle(this.$route.params.id, accessToken)

Solution

To enable type inference in the single file component, use Vue.extend() on the component declaration:

// EventSingle.vue (Vue 2)
import Vue from 'vue';
                    👇
export default Vue.extend({
  created() {
    this.getEventData(); // 💡 type inference now enabled
  }
})

In Vue 3, use defineComponent() instead:

// EventSingle.vue (Vue 3)
import{ defineComponent } from 'vue';
                    👇
export default defineComponent({
  created() {
    this.getEventData(); // 💡 type inference now enabled
  }
})

To declare the types for $auth on the Vue instance, create a .d.ts file in src/ with the following contents (and if using VS Code, restart IDE to properly index the file). The $auth property from the plugin only uses a subset of the Auth0Client interface, so we expose that same subset of the interface in the type augmentation:

// src/auth0.d.ts
import type Vue from 'vue'
import type { Auth0Client } from '@auth0/auth0-spa-js'

declare module 'vue/types/vue' {
  interface Vue {
    $auth: Pick<Auth0Client,
      | 'loginWithPopup'
      | 'handleRedirectCallback'
      | 'loginWithRedirect'
      | 'getIdTokenClaims'
      | 'getTokenSilently'
      | 'getTokenWithPopup'
      | 'logout'
    >
  }
}

export {}

Answered By – tony19

Answer Checked By – Timothy Miller (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *