nuxt-auth
nuxt-auth copied to clipboard
TypeScript: Can't extend callback params type
Environment
- Operating System: Darwin
- Node Version: v22.12.0
- Nuxt Version: 3.15.2
- CLI Version: 3.20.0
- Nitro Version: 2.10.4
- Package Manager: [email protected]
- Builder: -
- User Config: compatibilityDate, ssr, devtools, modules, runtimeConfig, auth
- Runtime Modules: @sidebase/[email protected]
- Build Modules: -
Reproduction
You don't need a repo to "reproduce" this issue, just add the @side-base/nuxt-auth model with "auth.js" as it provider then try to extend the callback parameters type using "declare module".
Just in case below is my "minimal" config in the completely new Nuxt 3 project.
nuxt.config.ts file
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: '2024-11-01',
ssr: false,
devtools: { enabled: true },
modules: ['@sidebase/nuxt-auth'],
runtimeConfig: {
authOrigin: '',
},
auth: {
isEnabled: true,
originEnvKey: 'NUXT_AUTH_ORIGIN',
baseURL: '/api/v1/auth',
provider: {
type: 'authjs',
trustHost: true,
defaultProvider: 'credentials',
addDefaultCallbackUrl: true,
},
globalAppMiddleware: true,
},
});
NuxtAuthHandler files, you can ignore almost all of it, just focus on the callback code:
import CredentialsProvider from 'next-auth/providers/credentials';
import { NuxtAuthHandler } from '#auth';
interface CustomUser {
id: string;
username: string;
password: string;
}
export default NuxtAuthHandler({
// A secret string you define, to ensure correct encryption
secret: 'C4A01200-A1C5-47F5-A392-3F693B973489',
providers: [
// @ts-expect-error Use .default here for it to work during SSR.
CredentialsProvider.default({
id: 'credentials',
name: 'Credentials',
credentials: {
username: { label: 'Username', type: 'text', placeholder: 'Username' },
password: {
label: 'Password',
type: 'password',
placeholder: 'Password',
},
},
async authorize(credentials: { username: string; password: string }) {
// Add logic here to look up the user from the credentials supplied
console.log(`=======================================`);
console.log(`Authorized credentials:`);
console.log(JSON.stringify(credentials));
console.log(`=======================================`);
const user = {
id: crypto.randomUUID(),
username: credentials.username,
// password: credentials.password,
};
console.log(`Credentials: ${JSON.stringify(user)}`);
if (credentials.username && credentials.password) {
// Any object returned will be saved in `user` property of the JWT
return user;
} else {
// If you return null then an error will be displayed advising the user to check their details.
return null;
// You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter
}
},
}),
],
// Callbacks should be here at the root level
callbacks: {
async signIn({ user, account, profile, email, credentials }) {
console.log(`------------------ BEFORE SIGN IN -------------------`);
console.log(user);
console.log(`------------------ BEFORE SIGN IN -------------------`);
return true;
},
async jwt({ token, user, account, profile, isNewUser }) {
console.log(`------------------JWT-------------------`);
console.log('JWT Callback - Input token:', token);
console.log('JWT Callback - Input user:', user);
console.log(`------------------JWT-------------------`);
if (user) {
return {
...token,
userData: {
// Store user data in a dedicated property
id: user.id,
username: user.username,
},
};
}
return token;
},
async session({ session, user, token }) {
console.log('Session Callback - Input session:', session);
console.log('Session Callback - Input token:', token);
// Make sure user data is copied to session
if (token.userData) {
session.user = token.userData;
}
console.log('Session Callback - Returning session:', session);
return session;
},
async redirect({ url, baseUrl }) {
console.log(`------------------ REDIRECT URL -------------------`);
console.log(url);
console.log(baseUrl);
console.log(`---------------------------------------------------`);
return url;
},
},
});
This part for more specific
if (user) {
return {
...token,
userData: {
// Store user data in a dedicated property
id: user.id,
username: user.username, <---------------- THIS IS WHERE THE ISSUE HAPPEN
},
};
}
The user.username got the below error:
Vue: Property username does not exist on type User | AdapterUser
Property username does not exist on type User
But I did extend that User interface/types like this:
import '#auth';
declare module '#auth' {
interface User {
id: string;
username: string;
password?: string;
}
}
And if I click to the User type when hover my mouse to the user I got property type as below:
export interface module:.auth. User {
id: string
username: string
}
shared/types/nuxt-auth.ts
Describe the bug
TypeScript: Cannot extend User type despite it being declared and visible in IDE and the official docs don't have any "section" on when using with TypeScript but the original package Auth.js have
I did describe this issue detailed in the Reproduction sections so I will not repeat it here.
I will be very appreciated, If anyone have same issue or have a solutions to this issue, please add a comment.
To this package dev teams, please add a document about TypeScript usage.
Additional context
No response
Logs