Next-auth: How to augment Session using TypeScript?

Created on 13 Sep 2020  路  10Comments  路  Source: nextauthjs/next-auth

Your question

Hi, would it be possible to add an example of type augmentation to the documentation?

What are you trying to do

I've modified what the session object returns and would like to augment the type defined in next-auth and next-auth/client to reflect the changes I've made. I've tried overriding the type definition by creating a next-auth.d.ts at the root of the project and included it in my tsconfig.json. However, VSCode uses the one defined by the module and not the one I've created (even though it recognizes that there are two type definitions).

To show what I have, here's the type definition I've created:

// next-auth.d.ts

import 'next-auth' 
import NextAuth from 'next-auth' 
import * as auth from 'next-auth' 
// import * as client from 'next-auth/client' 
// import 'next-auth/client' 

declare module 'next-auth' {
  export * from 'next-auth'
  export type InitOptions = auth.InitOptions
  export default NextAuth
  interface Session {
    user: {
      name: string
      email: string
      image: string
      uid: string
    }
  }
}

declare module 'next-auth/client' {
  export * from 'next-auth/client'

  export interface Session {
    user: {
      name: string
      email: string
      image: string
      uid: string
    }
  }
}


Any help would be appreciated.

Thank you.

Feedback
Documentation refers to searching through online documentation, code comments and issue history. The example project refers to next-auth-example.

  • [ ] Found the documentation helpful
  • [ ] Found documentation but was incomplete
  • [x] Could not find relevant documentation
  • [ ] Found the example project helpful
  • [x] Did not find the example project helpful
documentation question stale

Most helpful comment

I've just recently made the User model augmentable with @types/next-auth, by adding an auth.d.ts file with the contents below:

import "next-auth";

declare module "next-auth" {
  interface User {
    id: number; // Or string
  }
}

All 10 comments

I think I figured out. I believe this is a working type definition but in case someone would like to make a comment, I'll leave this issue open:

import 'next-auth'

/* Not sure if this is needed. */
// declare module 'next-auth' {
//   export interface Session {
//     uid: string
//   }
// }

declare module 'next-auth/client' {
  export interface Session {
    uid: string
  }
}

@iaincollins maybe we should add TypeScript example too?

Quick update:

So this does augment Session. However, it somehow breaks imports in VSCode (intellisense) for some reason. For now, I just // @ts-ignore the offending lines.

I think the main thing here is that Session might not necessarily _augment_ what's there by default, depending on what you've got in your callbacks -- it could be a totally different object. I think the right answer here to genericize it with a default of the default session and let the user define what Session should be right now, but for now I've just gone with the lazy route of facading useSession and getSession and typecasting to our app's actual session type.

(Also, maybe this would be better brought up in the DefinitelyTyped repo since next-auth has external type definitions -- although I've been looking at it and converting the whole thing to native TS seems like a fun project, I just wouldn't want to ruffle any feathers as a relatively first time contributor in the process)

@daviduzumeri Do you mind sharing how you do the typecasting?

@daviduzumeri Do you mind sharing how you do the typecasting?

Ya of course, scrubbing it of repo-specific stuff because I like continuing to receive a paycheck during a global pandemic I've actually got a function like this where RepoSession is the repo's session type:

import { IncomingMessage } from 'http'
import { NextApiRequest } from 'next'
import {
  getSession as nextAuthGetSession,
  useSession as nextAuthUseSession,
} from 'next-auth/client'
import { RepoSession } from '../types'

export async function getSession({
  req,
}: {
  req: IncomingMessage & { session?: RepoSession }
}): Promise<RepoSession | null> {
  if (!req.session) {
    const session = (await nextAuthGetSession({
      req: req as NextApiRequest,
    })) as RepoSession | null
    req.session = session ?? undefined
  }
  return req.session ?? null
}

export function useSession(): [RepoSession, boolean] {
  return nextAuthUseSession() as [RepoSession, boolean]
}

You might do an as unknown as RepoSession if you're not extending the next-auth Session type, but I just use this get and this hook everywhere instead of directly from next-auth and everything works for me. (It also caches the session on the request object so we don't keep hitting the session endpoint every time)

It's not SUPER clean, but at least the ugliness is entirely localized in this file.

I've just recently made the User model augmentable with @types/next-auth, by adding an auth.d.ts file with the contents below:

import "next-auth";

declare module "next-auth" {
  interface User {
    id: number; // Or string
  }
}

Hi there! It looks like this issue hasn't had any activity for a while. It will be closed if no further activity occurs. If you think your issue is still relevant, feel free to comment on it to keep it open. (Read more at #912) Thanks!

Hi there! It looks like this issue hasn't had any activity for a while. To keep things tidy, I am going to close this issue for now. If you think your issue is still relevant, just leave a comment and I will reopen it. (Read more at #912) Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

loonskai picture loonskai  路  3Comments

eatrocks picture eatrocks  路  3Comments

MelMacaluso picture MelMacaluso  路  3Comments

iaincollins picture iaincollins  路  3Comments

simonbbyrne picture simonbbyrne  路  3Comments