Auth-module: Typescript Types

Created on 27 Nov 2018  路  25Comments  路  Source: nuxt-community/auth-module

What problem does this feature solve?

Typescript types for $auth on the vue instance

This feature request is available on Nuxt community (#c219)
enhancement

Most helpful comment

WIP Types

Make sure you Replace User with your user object. I'm working on making this generic for the types to be included with the auth-module npm package.

/**
 * Augment the typings of Vue.js
 */

import Vue, { ComponentOptions } from "vue";
import { CookieAttributes } from "js-cookie";
import { User } from "../../server/services/v1/users/users.interface";

// todo: context?
interface StorageCookieOptions extends CookieAttributes {
  cookie: {
    prefix: string;
    options?: StorageCookieOptions;
  };
}
interface Storage {
  setUniversal(key: string, value: any, isJson?: boolean): string;
  getUniversal(key: string, isJson?: boolean): any;
  syncUniversal(key: string, defaultValue: any, isJson?: boolean): any;
  // Local State
  setState(key: string, val: any): string;
  getState(key: string): string;
  watchState(key: string, handler: (newValue: any) => void);
  // Cookies
  setCookie(key: string, val: any, options?: StorageCookieOptions);
  getCookie(key: string, isJson?: boolean): any;
  // Local Storage
  setLocalStorage(key: string, val: any, isJson?: boolean);
  getLocalStorage(key: string, isJson?: boolean): any;
}

interface Auth<T = any> {
  ctx: any;
  $state: any; // todo: type this
  $storage: Storage;
  user: Partial<T>;
  loggedIn: boolean;
  loginWith(strategyName: string, ...args): Promise<never>;
  login(...args): Promise<never>;
  logout(): Promise<never>;
  fetchUser(): Promise<never>;
  fetchUserOnce(): Promise<never>;
  hasScope(scopeName: string): boolean;
  setToken(strategyName: string, token?: string): string;
  syncToken(strategyName: string): string;
  onError(handler: (error: Error, name: string, endpoint: any) => void);
  setUser(user?: Partial<T>);
  reset(): Promise<never>;
  redirect(name: string);
}

declare module "vue/types/options" {
  interface ComponentOptions<V extends Vue> {
    auth?: boolean;
  }
}

declare module "vue/types/vue" {
  interface Vue {
    $auth: Auth<User>;
  }
}

updated 12/18

All 25 comments

I run into the same issue. For testing sake, I use some like this.

    //@ts-ignore
    if (this.$auth.loggedIn) {
        this.$router.push('/');
    }

but I don't recomend to use it all over the app, the code will look like crap.

WIP Types

Make sure you Replace User with your user object. I'm working on making this generic for the types to be included with the auth-module npm package.

/**
 * Augment the typings of Vue.js
 */

import Vue, { ComponentOptions } from "vue";
import { CookieAttributes } from "js-cookie";
import { User } from "../../server/services/v1/users/users.interface";

// todo: context?
interface StorageCookieOptions extends CookieAttributes {
  cookie: {
    prefix: string;
    options?: StorageCookieOptions;
  };
}
interface Storage {
  setUniversal(key: string, value: any, isJson?: boolean): string;
  getUniversal(key: string, isJson?: boolean): any;
  syncUniversal(key: string, defaultValue: any, isJson?: boolean): any;
  // Local State
  setState(key: string, val: any): string;
  getState(key: string): string;
  watchState(key: string, handler: (newValue: any) => void);
  // Cookies
  setCookie(key: string, val: any, options?: StorageCookieOptions);
  getCookie(key: string, isJson?: boolean): any;
  // Local Storage
  setLocalStorage(key: string, val: any, isJson?: boolean);
  getLocalStorage(key: string, isJson?: boolean): any;
}

interface Auth<T = any> {
  ctx: any;
  $state: any; // todo: type this
  $storage: Storage;
  user: Partial<T>;
  loggedIn: boolean;
  loginWith(strategyName: string, ...args): Promise<never>;
  login(...args): Promise<never>;
  logout(): Promise<never>;
  fetchUser(): Promise<never>;
  fetchUserOnce(): Promise<never>;
  hasScope(scopeName: string): boolean;
  setToken(strategyName: string, token?: string): string;
  syncToken(strategyName: string): string;
  onError(handler: (error: Error, name: string, endpoint: any) => void);
  setUser(user?: Partial<T>);
  reset(): Promise<never>;
  redirect(name: string);
}

declare module "vue/types/options" {
  interface ComponentOptions<V extends Vue> {
    auth?: boolean;
  }
}

declare module "vue/types/vue" {
  interface Vue {
    $auth: Auth<User>;
  }
}

updated 12/18

Please post suggestions for improvements if you have any, I'll put a PR together at some point, I think there are a few issues with these typings that need to be fixed before that though.

Using Promise<never> implies that the Promise is never resolved. I think you wanted to write Promise<void>, which translates to a promises which resolves without a value.

@NickBolles I'm a typescript noob. Where do I put that code?

@ryanwinchester Add it to a file called index.d.ts in your root directory.

Alternatively, you could also set up a types directory with a number of type declaration files, in which case I would add this content as another file in that directory, making sure it was listed in tsconfig.json under compilerOptions.typeRoots.

What's the status on this?

Can it be supported by default?
Ideally we just have to add @nuxtjs/auth to the types array of tsconfig.json like most other modules.

FYI - made a PR to definitely typed using @NickBolles's approach: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/38132

FYI - made a PR to definitely typed using @NickBolles's approach: DefinitelyTyped/DefinitelyTyped#38132

I think the Promises should be of type Promise<void> instead of type Promise<never> as mentioned above. Correct me if I'm wrong.

@jonnyparris Looks like that PR is merged now. Should we close this?

@NickBolles sure
@laflo feel free to make a PR there too, sorry I missed it first time around

Guys, please explain how to include this type.
Can we now add @nuxtjs/auth to the types array of tsconfig.json like most other modules.?

Almost; you need to add @types/nuxtjs__auth to the tsconfig.json > compilerOptions > types array.

Make sure you've also added @types/nuxtjs__auth as a devDependency in your project.

I submitted a PR to make this more automatic. See #486

To resolve this.$auth in vuex typescript modules, I had to add the following

types/vue-shim.d.ts better to add to new file types/vue-nuxtauth.d.ts

import { Auth } from '@nuxtjs/auth'

declare module 'vuex/types/index' {
    interface Store<S> {
        $auth: Auth,
    }
}

I still have this issue in my NuxtJS project...

 ERROR  ERROR in @/layouts/app.vue(109,12):
109:12 Property '$auth' does not exist on type 'CombinedVueInstance<Vue, AppData, {....}, {....}, Readonly<unknown>>'.
    107 |     },
    108 |     logout() {
  > 109 |       this.$auth.logout()
        |            ^
    110 |         .then(() => {
    111 |           let logoutUrl = new URL(`https://${this.$auth.strategies.auth0.options.domain}/v2/logout`);
    112 |           let { origin } = new URL(document.URL);

Not sure what to do to fix it...

@Micka33 did you add "@types/nuxtjs__auth" to your types array in the tsconfig.json?

Just did it, and my editor displays the following:
Screenshot 2020-07-06 at 11 57 41

Should install something more than @nuxtjs/auth ?
EDIT:
I ran npm install @types/nuxtjs__auth and my editor is not showing any error in tsconfig.json anymore.

If you need just to add typings for this.$auth (and context.$auth), add this in your type declaration file

import Auth from '@nuxtjs/auth/lib/core/auth'

declare module 'vue/types/vue' {
  interface Vue {
    $auth: Auth
  }
}

For @nuxtjs/auth-next my vue-nuxtauth.d.ts looks the following:

import Auth from '@nuxtjs/auth-next/dist/core/auth'

declare module 'vue/types/vue' {
  interface Vue {
    $auth: Auth
  }
}
import Auth from '@nuxtjs/auth-next/dist/core/auth'

declare module 'vue/types/vue' {
  interface Vue {
    $auth: Auth
  }
}

Hi, mind if i ask where to put this? should i put this in store folder? thanks

@fahmiegerton You could put that in an index.d.ts file in your source directory.

@fahmiegerton You could put that in an index.d.ts file in your source directory.

@danielroe I couldn't find any file named index.d.ts in my root project. Should I create this file first? Thanks

@fahmiegerton Yes 馃憤

@fahmiegerton Yes 馃憤

Oh okay, thank you very much!

Was this page helpful?
0 / 5 - 0 ratings