Next.js14集成NextAuth遇TS类型错误:string|undefined无法赋值
Next.js 14 + NextAuth 凭证登录 TypeScript 类型错误解决
问题场景
在Next.js 14项目中集成NextAuth实现凭证登录,对比用户输入密码与数据库存储密码时,遇到TypeScript类型错误:
"Argument of type 'string | undefined' is not assignable to parameter of type 'string | Buffer'."
错误触发代码行:
const passwordOk = existingUser && bcrypt.compareSync(password, existingUser.password)
完整配置代码如下:
import CredentialsProvider from "next-auth/providers/credentials" import type { NextAuthOptions } from "next-auth" import connectMongoDB from "@/lib/mongodb" import bcrypt from "bcrypt" import User from "@/models/user" export const authOptions: NextAuthOptions = { providers: [ CredentialsProvider({ name: "Credentials", credentials: { email: {}, password: {}, }, async authorize(credentials, req) { const email = credentials?.email const password = credentials?.password await connectMongoDB() const existingUser = await User.findOne({ email }) const passwordOk = existingUser && bcrypt.compareSync(password, existingUser.password) if (passwordOk) { return existingUser } else { return null } }, }), ], }
错误原因
credentials?.password使用了可选链操作符,导致password的类型为string | undefined,而bcrypt.compareSync的第一个参数要求是string | Buffer,不允许传入undefined,TypeScript严格类型检查下就会抛出错误。
你尝试手动指定const password: string | Buffer = credentials?.password无效,是因为credentials?.password可能为undefined,无法直接赋值给不包含undefined的类型。
解决方案
方案1:提前校验参数(推荐)
在逻辑开始处先校验credentials及其中的email、password是否存在,提前返回null或抛出错误,确保后续变量类型确定:
async authorize(credentials, req) { // 提前校验参数完整性 if (!credentials?.email || !credentials?.password) { return null; // 也可抛出错误:throw new Error("请输入邮箱和密码") } // 此时email和password都是确定的string类型 const email = credentials.email; const password = credentials.password; await connectMongoDB() const existingUser = await User.findOne({ email }) const passwordOk = existingUser && bcrypt.compareSync(password, existingUser.password) if (passwordOk) { return existingUser } else { return null } },
方案2:短路求值判断(你尝试的方法)
通过password &&的短路判断,确保只有当password存在时才执行compareSync,避免传入undefined:
const passwordOk = existingUser && password && bcrypt.compareSync(password, existingUser.password)
这种方法能消除类型错误,是可行的,但提前校验参数的方式代码可读性更强,也能更早拦截无效请求。
内容的提问来源于stack exchange,提问作者Muhammad Rabi
相关产品推荐
相关产品推荐

