Utilizing Provide/Inject in Vue 3 Typescript to retrieve a method within a component, encountering the possibility of an 'undefined' Error Object

Having trouble calling the loginWithRedirect function within the header.vue component using inject feature in Vue 3 and Typescript.

ERROR in src/components/global/HeaderMenu.vue:77:17 TS2339: Property 'loginWithRedirect' does not exist on type 'Auth0Plugin'. 75 | methods: { 76 | login() {

77 | this.auth.loginWithRedirect(); | ^^^^^^^^^^^^^^^^^ 78 | }, 79 | logout() { 80 | // this.$AuthPlugin.logout();

I'm a newbie to Typescript and facing challenges with the usage of inject in the context of Typescript and Vue 3. The initial issue was addressed here. According to my interpretation, I followed these steps:

​async function init() {
     ​const AuthPlugin = await Auth0.init({
       ​onRedirectCallback: (appState) => {
         ​router.push(appState && appState.targetUrl ? appState.targetUrl : window.location.pathname);
       ​},
       ​clientId: 'xxxx',
       ​domain: 'xxxx',
       ​audience: 'xxxx'
     ​});
     ​const app = createApp(App);
     ​// library.add(faLink, faUser, faPowerOff);
     ​app
       ​.use(AuthPlugin)
       ​.use(router)
       ​.use(BootstrapVue3)
       ​.provide('authPlugin', AuthPlugin)
       ​.mount('#app');
   ​}
   ​
   ​init();

In my header.vue component, I aim to utilize loginWithRedirect from auth index.ts. To achieve this, I included the following code snippet in components/header.vue...

Imported and set type

   ​import { defineComponent } from 'vue';
   ​import { inject } from 'vue';
   ​import { Auth0 } from '@/auth';
   ​export type TAuthPlugin = typeof Auth0;

​Within the setup() method of the same header.vue component...

   ​setup() {
       ​const auth = inject<TAuthPlugin>('Auth');  

This seems to grant access to the login method via this.auth

https://i.sstatic.net/9cF9C.png

However, when attempting to access this.auth.login, an error occurs. Why is that?

src/components/global/HeaderMenu.vue:77:7
TS2532: Object is possibly 'undefined'.
    75 |   methods: {
    76 |     login() {
  > 77 |       this.auth.loginWithRedirect();
       |       ^^^^^^^^^
    78 |     },
    79 |     logout() {
    80 |       // this.$AuthPlugin.logout();

header.vue

<script lang="ts">
import { defineComponent } from 'vue';
import { inject } from 'vue';
import { Auth0 } from '@/auth';
export type TAuthPlugin = typeof Auth0;
export default defineComponent({
  name: 'HeaderMenu',
  inject: ['authPlugin'],
  methods: {
    login() {
      this.auth.loginWithRedirect();
    },
    logout() {
      // this.$AuthPlugin.logout();
      this.$router.push({ path: '/' });
    },
  },
  setup() {
    const auth = inject<TAuthPlugin>('Auth');
    
    return {
      auth,
    };
  },
});
</script>

The content of the auth index.ts for reference.

(Content of auth index.ts - omitted)

​​1: Vue 3 with Typescript inject does not work as intended. Spread types may only be created from object types

Answer №1

The issue lies in the fact that the objects authPlugin and Auth0 are not related to each other.

The solution would be to use either

provide('authPlugin', authPlugin)
and
inject<typeof authPlugin>('authPlugin')
, or provide('authPlugin', Auth0) and
inject<typeof Auth0>('authPlugin')
.

In this particular scenario, using inject is unnecessary. This method is usually employed for establishing loose coupling in third-party plugins, or for implementing deep dependency injection in nested components. Unless there is a specific requirement for authentication to function as a separate entity within the application design, it does not need to be treated as a plugin with provide/inject. Since authPlugin is defined at the time of module evaluation, it can simply be exported from the auth module and imported wherever necessary.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Changing a single image within a v-for loop of images in Vue

I am currently working with an array in Vue where I am using v-for to create 3 columns of information. Each column includes an image, and I would like to be able to change only the specific image that is being hovered over without affecting any others. How ...

Translating Python's slicing assignment syntax to JavaScript/TypeScript: A guide

Currently, I am in the process of converting a Python library into TypeScript. One specific challenge I am facing is translating this line of code from this particular repository: is_prime[start - segment_min::pk] = repeat(False, len(range(start - segment ...

Help me figure out how to independently toggle submenus on my navbar by utilizing the Vue.js composition API

I am currently working on developing a navbar using the Vue.js composition API. My primary objective is to toggle the submenus when a user clicks on them. However, since I am iterating through an object to display the submenus, I am faced with the challeng ...

(Vue.js) The icon fails to be applied

<link rel="icon" href="/static/icons/apple-touch-icon.png" type="image/x-icon"> <link rel="icon" type="image/png" sizes="32x32" href="/static/icons/apple-touch-icon.png"> <link rel="icon" type="image/png" sizes="16x16" href="/static/ ...

Enhance the TypeScript interface by dynamically appending new fields with specific naming conventions

My interface is structured like this: interface ProjectCostData { purchasePrice: number; propertyValue: number; recentlyDamaged: boolean; } Now I am looking to dynamically create a new interface based on the one above: interface ProjectCostDataWithS ...

iterate through all the items in the radioButton collection

Hello, I am looking to iterate through this object and display checkbox values along with their indices. data: [ { key1: 'last 6 months' }, { key2: 'last 30 days' } ] I would like to creat ...

Vue.js array dependencies

In Vue JS, I encountered an issue with empty arrays declared in the data. Initially, array A is populated with a hundred nested arrays. When a user interacts by clicking on a specific element, I need to extract the corresponding element from array A and pr ...

Error in parsing: Unexpected token encountered. Expected a comma instead. Issue found in React with Typescript

I'm encountering a new error message that I haven't seen before... I've checked my code thoroughly and it seems to be correct, yet the error persists. Here is my code snippet: interface AuthState { token: string; user: User; } interfac ...

What causes regular objects to become automatically reactive in Vue3?

There is an example discussed in this particular article. It mentions that a normal object is not 'reactive'. Upon testing in this codesandbox environment, it was observed that changes made to the normal object, including a plain string, can aut ...

What methods can I use to verify that a Vue component reacts to an event broadcasted by $root?

There's a component in my Vue app that listens for an event emitted by the $root instance. export default { data() { return { name: '' } }, methods: { openModal(name) { this.name = name } }, ...

Issue with retrieving properties in Angular template due to undefined values in HTML

As a newbie to Angular, I am dedicated to improving my skills in the framework. In my project, I am utilizing three essential files: a service (Studentservice.ts) that emits an observable through the ShowBeerDetails method, and then I subscribe to this ob ...

What is the best way to ensure that a mapped type preserves its data types when accessing a variable?

I am currently working on preserving the types of an object that has string keys and values that can fall into two possible types. Consider this simple example: type Option1 = number type Option2 = string interface Options { readonly [key: string]: Op ...

Is Babel necessary for enabling JavaScript compatibility in my TypeScript React project, excluding Create React App?

This is the webpack configuration for my React project built in TypeScript, module.exports = { mode: 'development', entry: ['./src/main.tsx'], module: { rules: [ { // Rule for ts/tsx files only, no rule for js/js ...

What is the best way to divide my Vue.js project into separate sections for development and testing purposes?

I am looking to split my vuejs frontend project into two sections: development and testing. For the development section, I want to work locally and make requests to the example:8010 url, while for the testing section, I need to send requests to the example ...

Exploring Laravel and Vue: A guide to extracting URL parameters in Vue

I have included an id in the URL like this: (). Now, I am trying to retrieve that id in Vue in order to fetch data specifically for that id. However, I am unsure how to obtain the id in Vue. Below is my Vue script: <script> export default ...

Is it possible to customize the default typography settings for Textfields and other components using a theme in Material UI v5?

Is there a method to customize the default typography for TextField and all inputs using themes? I am aware of this approach: components: { MuiInput: { styleOverrides: { root: { fontSize: '16px', ...

The dropdown in vue-multiselect automatically closes after the first selection is made, ensuring a smooth user experience. However,

I am experiencing an issue where the dropdown closes after the first selection, despite setting close-on-select="false". However, it works properly after the initial select. You can observe this behavior directly on the homepage at the following link: vue ...

Using ts-node-dev (and ts-node) with ECMAScript exports and modules

Currently, we are in the process of upgrading TypeScript to a more modern standard due to changes in libraries like nanoid that no longer support commonjs exports. Our goal is to integrate the ts-node-dev library with exporting to ECMAScript modules. The ...

Change the name of the state in Vue mapState

I have a specific situation in my computed where I need to track two different "loading" states. Is there a method to include an alias for the second state using this syntax? computed: { ...mapState('barcodes', ['barcodes', ' ...

Nodemailer fails to display an error message when the email is not successfully sent

I am currently working on implementing nodemailer for sending emails. However, I noticed that if the email address in the "to" field is incorrect, the email is not sent as expected. The issue is that there is no error displayed and the function still resol ...