You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AuthJS扩展session.user对象时遭遇TypeError问题求助

扩展NextAuth Session.user对象时的类型错误问题

问题代码

尝试扩展NextAuth的session.user对象添加自定义字段,代码如下:

import "next-auth";
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import type { NextAuthConfig } from "next-auth";

declare module "next-auth" {
  interface User {
    group: string;
    avatar: string;
  }
}

export const config = {
  pages: {
    signIn: "/signin",
  },
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: {
          label: "Email",
          type: "email",
          placeholder: "Email (@mobifone.vn)",
        },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        const authResponse = await fetch(
          "http://localhost:9000/api/v1/auth/signin",
          {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({
              username: credentials.email,
              password: credentials.password,
            }),
          }
        );

        if (!authResponse.ok) {
          return null;
        }

        const res = await authResponse.json();

        return res.user;
      },
    }),
  ],
  callbacks: {
    async session({ session, token, user }) {
      return {
        ...session,
        user: {
          ...session.user,
          group: user.group,
          avatar: user.avatar,
        },
      };
    },
  },
} satisfies NextAuthConfig;

export const { handlers, auth, signIn, signOut } = NextAuth(config);

错误信息

Type '({ session, token, user }: { session: Session; token: JWT; user: AdapterUser; } & { newSession: any; trigger: "update"; }) => Promise<{ user: { group: string; avatar: string; id?: string | undefined; name?: string | ... 1 more ... | undefined; email?: string | ... 1 more ... | undefined; image?: string | ... 1 more ...' is not assignable to type '(params: { session: Session; token: JWT; user: AdapterUser; } & { newSession: any; trigger: "update"; }) => Awaitable<Session | DefaultSession>'.
  Type 'Promise<{ user: { group: string; avatar: string; id?: string | undefined; name?: string | null | undefined; email?: string | null | undefined; image?: string | null | undefined; }; expires: string; }>' is not assignable to type 'Awaitable<Session | DefaultSession>'.
    Type 'Promise<{ user: { group: string; avatar: string; id?: string | undefined; name?: string | null | undefined; email?: string | null | undefined; image?: string | null | undefined; }; expires: string; }>' is not assignable to type 'PromiseLike<Session | DefaultSession>'.
      Types of property 'then' are incompatible.
        Type '<TResult1 = { user: { group: string; avatar: string; id?: string | undefined; name?: string | null | undefined; email?: string | null | undefined; image?: string | null | undefined; }; expires: string; }, TResult2 = never>(onfulfilled?: ((value: { ...; }) => TResult1 | PromiseLike<...>) | ... 1 more ... | undefined,...' is not assignable to type '<TResult1 = Session | DefaultSession, TResult2 = never>(onfulfilled?: ((value: Session | DefaultSession) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<...>) | ... 1 more ... | undefined) => PromiseLike<...>'.
          Types of parameters 'onfulfilled' and 'onfulfilled' are incompatible.
            Types of parameters 'value' and 'value' are incompatible.
              Type '{ user: { group: string; avatar: string; id?: string | undefined; name?: string | null | undefined; email?: string | null | undefined; image?: string | null | undefined; }; expires: string; }' is not assignable to type 'Session | DefaultSession'.
                Type '{ user: { group: string; avatar: string; id?: string | undefined; name?: string | null | undefined; email?: string | null | undefined; image?: string | null | undefined; }; expires: string; }' is not assignable to type 'DefaultSession'.
                  The types of 'user.id' are incompatible between these types.
                    Type 'string | undefined' is not assignable to type 'string'.
                      Type 'undefined' is not assignable to type 'string'.ts(2322)

无效尝试

尝试手动添加id字段隐藏错误,但无法完成登录:

callbacks: {
  async session({ session, token, user }) {
    return {
      ...session,
      user: {
        ...session.user,
        id: user.id,
        group: user.group,
        avatar: user.avatar,
      },
    };
  },
},

解决方案

1. 完整扩展TypeScript接口

不仅要扩展User接口,还要扩展Session接口,确保session.user的类型与DefaultSession兼容,且自定义字段类型正确:

import "next-auth";
import type { DefaultSession } from "next-auth";

declare module "next-auth" {
  interface User {
    id: string; // 确保User包含id字段,与后端返回一致
    group: string;
    avatar: string;
  }

  interface Session {
    user: {
      group: string;
      avatar: string;
    } & DefaultSession["user"]; // 合并默认User字段,保证id、name等字段类型正确
  }
}

2. 正确同步用户信息到Session

Credentials模式下,用户信息会先存入JWT Token,再同步到Session。依赖session回调中的user参数不可靠(仅登录首次回调存在),需通过jwt回调中转:

callbacks: {
  // 将自定义字段存入JWT Token
  async jwt({ token, user }) {
    if (user) {
      token.id = user.id;
      token.group = user.group;
      token.avatar = user.avatar;
    }
    return token;
  },
  // 从Token同步字段到Session
  async session({ session, token }) {
    if (session.user) {
      session.user.id = token.id as string;
      session.user.group = token.group as string;
      session.user.avatar = token.avatar as string;
    }
    return session;
  },
},

3. 确保后端返回字段完整

确认/api/v1/auth/signin接口返回的res.user包含id、group、avatar三个必填字段,否则TypeScript会在authorize函数中报错。

内容的提问来源于stack exchange,提问作者Minh Thông

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:14:53