I'm encountering the following TypeScript error:
"Argument of type 'string | undefined' is not assignable to parameter of type 'string | Buffer'."
I'm integrating NextAuth with my Next.js 14 application and configuring login credentials to compare passwords during login. However, I'm facing this error specifically with the input password in the following line:
const passwordOk =
existingUser && bcrypt.compareSync(password, existingUser.password)
and this is the full options file
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 = {
// Configure one or more authentication providers
providers: [
CredentialsProvider({
name: "Credentials",
credentials: {
// email: { label: "Email", type: "email", placeholder: "email" },
// password: { label: "Password", type: "password" },
email: {},
password: {},
},
async authorize(credentials, req) {
const email = credentials?.email
const password = credentials?.password
// Add logic here to look up the user from the credentials supplied
await connectMongoDB()
const existingUser = await User.findOne({ email })
const passwordOk =
existingUser && bcrypt.compareSync(password, existingUser.password)
if (passwordOk) {
// Any object returned will be saved in `ser` property of the JWT
return existingUser
} 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
}
},
}),
],
}
I have tried to assign this type manually on the password but didn't work
const password: string | Buffer = credentials?.password
I also tried this
const passwordOk =
existingUser &&
password &&
bcrypt.compareSync(password, existingUser.password)
and the error disappeared, but I'm not sure if it is a best practice
credentials?.password
might return undefined
because of Optional chaining ?.
and compareSync
couldn't be evaluated with an undefined
as a first parameter, hence, you are seeing this error.
The optional chaining (?.) operator accesses an object's property or calls a function. If the object accessed or function called using this operator is
undefined
ornull
, the expression short circuits and evaluates toundefined
instead of throwing an error.
Since passwordOk
will be affected by password
value, it's recommended to check for its value (and for the email as well) before continuing with the excution, though, a Guard Clause would be great here:
const email = credentials?.email;
const password = credentials?.password;
if (!email || !password) return;
// rest of the code
This should remove the error.
Another solution that I don't really recommend in such cases (due to somehow breaking the typescript checking system) is to use non-null assertion operator and the syntax is pretty easy, simply postfix your password with exclamation mark, i.e. credentials.password!
this tells typescript that you are pretty sure that this expression will return a value and will never be null
or undefined
.