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

Next.js+TypeScript下扩展useSession用户属性的类型错误解决

在Next.js + TypeScript中扩展NextAuth useSession返回的用户对象类型

你遇到的问题核心是直接修改node_modules中的类型文件无法持久生效(依赖更新后会被覆盖),且不符合TypeScript的类型扩展规范。正确的做法是通过**模块扩展(Module Augmentation)**在项目内自定义NextAuth的类型,以下是完整解决方案:


1. 还原node_modules中的类型文件

直接修改node_modules/next-auth/src/core/types.ts是临时方案,npm install/yarn install后所有修改会被覆盖,必须完全还原这些文件。

2. 创建项目专属的NextAuth类型声明文件

在项目根目录(或src目录下)创建types/next-auth.d.ts文件,通过TypeScript的模块扩展功能覆盖NextAuth的内置类型:

import NextAuth from "next-auth";

// 扩展Session接口,添加自定义用户属性
declare module "next-auth" {
  interface Session {
    user: {
      id: string;
      iat: number;
      exp: number;
      jti: string;
      name?: string | null;
      email?: string | null;
      image?: string | null;
    };
  }

  // 扩展User接口,匹配authorize返回的用户结构
  interface User {
    id: string;
    token?: string; // 对应你authorize中返回的user.token
    name?: string | null;
    email?: string | null;
    image?: string | null;
  }
}

// 扩展JWT接口,确保token包含自定义属性
declare module "next-auth/jwt" {
  interface JWT {
    id: string;
    iat: number;
    exp: number;
    jti: string;
    user?: User;
  }
}

3. 调整[...nextauth]中的回调逻辑

优化jwt和session回调,确保属性正确传递,同时利用扩展后的类型(无需手动类型断言):

// src/api/auth/[...nextauth].ts
import NextAuth, { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import axios from "axios";

const nextAuthOptions: NextAuthOptions = {
  providers: [
    CredentialsProvider({
      name: "credentials",
      credentials: {
        email: { label: "email", type: "text" },
        password: { label: "password", type: "password" },
      },

      async authorize(credentials, _) {
        const response = await axios.post(
          "http://localhost:4000/auth/login",
          {
            email: credentials?.email,
            password: credentials?.password,
          },
          {
            headers: { "Content-type": "application/json" },
          }
        );

        const user = response.data.data;
        // 确保返回的user包含id和token
        if (user.id && user.token) {
          return user;
        }

        return null;
      },
    }),
  ],
  pages: {
    signIn: "/sign-in2",
  },
  callbacks: {
    async jwt({ token, user }) {
      // 当用户首次登录时,将user的id赋值给token
      if (user) {
        token.id = user.id;
      }
      // token本身自带iat、exp、jti属性,无需手动赋值
      return token;
    },
    async session({ session, token }) {
      // 将token中的属性同步到session.user
      session.user.id = token.id;
      session.user.iat = token.iat;
      session.user.exp = token.exp;
      session.user.jti = token.jti;
      return session;
    },
  },
};

const handler = NextAuth(nextAuthOptions);
export { handler as GET, handler as POST, nextAuthOptions };

4. 验证组件中的类型支持

在Cart组件中,useSession返回的data.user现在会自动识别新增的属性,TypeScript不再报错:

const handleFinishPurchaseClick = async () => {
  if (!data?.user) {
    return alert("Fazer o Login");
  }
  // 此处data.user.id会被TypeScript正确识别为string类型
  const order = await axios.post("http://localhost:4000/orders", {
    user_id: data.user.id,
  });
  console.log(order);
};

5. 确保TypeScript识别自定义类型

检查项目的tsconfig.json,确保include字段包含我们创建的类型文件:

{
  "compilerOptions": {
    // 其他配置...
  },
  "include": ["types/**/*.d.ts", "src/**/*"],
  "exclude": ["node_modules"]
}

内容的提问来源于stack exchange,提问作者Renan França

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 02:20:59