Type Extension Problem in nuxt-auth-utils
Problem
I'm having issues extending the types for user sessions in nuxt-auth-utils. Despite following TypeScript module declaration best practices, the custom types are not being recognized when using setUserSession.
Environment
- Nuxt version: 3.17.4
- nuxt-auth-utils version: 0.5.20
- TypeScript version: 5.8.3
- Project structure: Monorepo (using Moon), but the Nuxt app functions independently
The issue When calling setUserSession(event, { ... }), TypeScript doesn't recognize my custom type definitions from my auth.d.ts file
What I've tried
- Created a auth.d.ts file
- Tried adding explicit configuration for nuxt.config.ts
export default defineNuxtConfig({ typescript: { shim: false, typeCheck: true, tsConfig: { include: ['types/**/*.d.ts'] } } // rest of configuration })
Workarounds tried
As a temporary workaround, I've had to use:
I've also been having this issue, "extending" the types doesn't even seem to give useful intellisense in the current state of the playground, however it does seem to be extending correctly:
no intellisense
succuessful extending
This is different than the behaviour I'm seeing in my own project:
- When I include
export {}in myauth.d.tslike suggested, it has no effect. This makes sense to me becauseexport {}should be overriding .d.ts from being an ambient module and instead just being a normal module (having no global effect) - When I omit
export {}in myauth.d.ts, thedeclare module '#auth-utils'statement replaces the pre-existing'#auth-utils'module, rather than merging with it. This makes most the utils have most typings resolve toany, (I assume because it's trying to import types from'#auth-utils'that no longer exist)
The only workaround I've found so far for this, is to create a local module:
workaround module
// modules/auth-types/index.ts
import { addTypeTemplate, createResolver, defineNuxtModule } from 'nuxt/kit'
export default defineNuxtModule({
setup() {
const resolver = createResolver(import.meta.url)
addTypeTemplate({
filename: 'types/auth.d.ts',
src: resolver.resolve('./auth.d.ts'),
}, { nitro: true, nuxt: true })
},
})
// modules/auth-types/auth.d.ts
declare module '#auth-utils' {
interface UserSession {
loggedInAt: number
}
}
export {}
You can see this finally worked for me
Even with the intended behvaiour, it doesn't even seem like UserSession can ever be well-typed because it has a [x: string]: any index signature which basically removes all type information from the interface. It's possible to extract the literal keys and their types from the interface manually with mapped types, so there may be another hacky workaround that's possible.
This seems like a DX bug though, because you can see in my first screenshot that even in this module's playground environment the UserSession isn't well-typed...
Hey @Vap0r1ze are you using compatibilityVersion 4 or Nuxt >= 4?
I had the same issue and added a PR to document a fix for me:
https://github.com/atinux/nuxt-auth-utils/pull/437
TL;DR - move the auth.d.ts file to the shared/ directory.
Hey @Vap0r1ze are you using compatibilityVersion 4 or Nuxt >= 4?
when I wrote this I wasn't, but today I turned on compatibilityVersion 4 for shared/utils imports so I'll give that a try! tyy
the same problem
@Eckhardt-D worked, tysm! imo upgrading to compatibilityVersion 4 is a fine solution, the only breaking change i had to undo was disabling noUncheckedIndexedAccess in nuxt's tsconfig
@MilesWuCode the type error in your screenshot is always gonna happen even when it's working, because the module's server files are excluded from the tsconfig. you should prob post a screenshot of the errors you get in your project files
the same problem
@MilesWuCode The #auth-utils in node_modules will always be unresolvable as it doesn't trace back to Nuxt's aliases. The app relies on the type aliases in tsconfig to resolve it in your working directory. You don't need to worry about that in node_modules. The issue arises in own usage of setUserSession, requireUserSession etc.
@MilesWuCode @Vap0r1ze Also, I think a hack on v3 would be to have a copy of auth.d.ts in root of project and also in the server directory. Not ideal and not sure if it'll work - but think it should.
@MilesWuCode @Vap0r1ze Also, I think a hack on v3 would be to have a copy of
auth.d.tsin root of project and also in theserverdirectory. Not ideal and not sure if it'll work - but think it should.
Move ./auth.d.ts to ./shared/auth.d.ts Typecheck succeeded
Also, I think a hack on v3 would be to have a copy of
auth.d.tsin root of project and also in theserverdirectory. Not ideal and not sure if it'll work - but think it should.
Not sure this would work because v3's .nuxt/tsconfig.server.json already has "../**/*" in its include, so I'd assume theres something else interfering. Though I can't even reproduce the issue again so it's still possible that works.
I still have issue with #433 but for now I'm resolving it with pnpm patch
Some notes that can help figuring out what's wrong:
-
export {}is required on every typescript file unless the fileimports anything. Otherwise typescript will treat the file as "not a module" and trigger all sort of legacy compatibility options that will make your life harder. - The
typescript.tsConfigoption in nuxt config refers to app (client) configuration. If you put your type declarations in a custom directory, usetypescript.sharedTsConfigoption instead. If you're on nuxt 4+ it's still better to put the files in theshareddirectory. - For editor features to work it is important that it picks up the right tsconfig for the file you are working on. Most guides assumes the root
tsconfig.jsonfile on your repository to be the same as it is configured by default, that is:
{
// https://nuxt.com/docs/guide/concepts/typescript
"files": [],
"references": [
{
"path": "./.nuxt/tsconfig.app.json"
},
{
"path": "./.nuxt/tsconfig.server.json"
},
{
"path": "./.nuxt/tsconfig.shared.json"
},
{
"path": "./.nuxt/tsconfig.node.json"
}
]
}
If you require any tsconfig customization you should rely on nuxt config to apply it to the generated files (using typescript.tsConfig for app, typescript.sharedTsConfig for shared, typescript.nodeTsConfig for nuxt.config.ts itself and nitro.typescript.tsconfig for server), rather than editing directly your tsconfig file.
as for setUserSession: the problem is that setUserSession does not use directly UserSession as type but rather Omit<UserSession, 'id'> which is problematic because Omit interacts weirdly with index signatures removing all string keys (something like this:)
Omit<UserSession, 'id'> =
Pick<UserSession, Exclude<keyof UserSession, 'id'>> =
Pick<UserSession, Exclude<string | 'id' | ... , 'id'>> =
Pick<UserSession, Exclude<string, 'id'>> =
Pick<UserSession, string extends 'id'? never : string > =
Pick<UserSession, never> =
{ [P in never]: UserSession[P] } =
{ }
A solution would be to define UserSession to not have any index signatures (see #433) and eventually add index signatures to methods that need to preserve backward compatibility (such as setUserSession)