[TS Error] user.locale missing in Better Auth type after adding custom field

I added a custom locale field via additionalFields in Better Auth, but TypeScript still throws: Property 'locale' does not exist on type '{ id: string; name: string; emailVerified: boolean; email: string; createdAt: Date; updatedAt: Date; image?: string | null | undefined; }'.ts(2339)
DB:
export const user = pgTable("user", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified")
.$defaultFn(() => false)
.notNull(),
image: text("image"),
locale: localeEnum("locale")
.$default(() => "en")
.notNull(),
createdAt: timestamp("created_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: timestamp("updated_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
});

auth.ts:
user: {
additionalFields: {
locale: {
type: "string",
required: true,
defaultValue: "en",
},
},
},
// Usage inside sendResetPassword / sendVerificationEmail callbacks:
const userLocale = user.locale || "en"; // ❌ TS2339
DB:
export const user = pgTable("user", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified")
.$defaultFn(() => false)
.notNull(),
image: text("image"),
locale: localeEnum("locale")
.$default(() => "en")
.notNull(),
createdAt: timestamp("created_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: timestamp("updated_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
});

auth.ts:
user: {
additionalFields: {
locale: {
type: "string",
required: true,
defaultValue: "en",
},
},
},
// Usage inside sendResetPassword / sendVerificationEmail callbacks:
const userLocale = user.locale || "en"; // ❌ TS2339
How do I properly type the custom locale field so it appears on the Better Auth User type?
6 Replies
nikatune
nikatune2mo ago
did u inferred it to auth-client.ts file?
ddev
ddevOP2mo ago
no i didnt, let me try it
nikatune
nikatune2mo ago
thats why sir
ddev
ddevOP2mo ago
wait, but there is probably nothing in common, coz i am getting error in server auth.ts when i am trying to send an email
emailAndPassword: {
enabled: true,
requireEmailVerification: true,
autoSignIn: false,
autoSignInAfterVerification: true,
sendResetPassword: async ({ user, token }) => {
const resetLink = `${process.env.APP_URL}/reset-password?token=${token}`;
const userLocale = user.locale || "en";
await emailOrchestrator.sendAndLogForgotEmail({
to: user.email,
url: resetLink,
userId: user.id,
locale: userLocale,
});
},
},
emailAndPassword: {
enabled: true,
requireEmailVerification: true,
autoSignIn: false,
autoSignInAfterVerification: true,
sendResetPassword: async ({ user, token }) => {
const resetLink = `${process.env.APP_URL}/reset-password?token=${token}`;
const userLocale = user.locale || "en";
await emailOrchestrator.sendAndLogForgotEmail({
to: user.email,
url: resetLink,
userId: user.id,
locale: userLocale,
});
},
},
Ping
Ping
Ping2mo ago
Yeah that's an issue with Better-auth where any user or session or anything related to those type are not inferred within the auth config. If you console.log the user you will likely see those fields, you can freely type assert to overwrite the types.
ddev
ddevOP2mo ago
Solution:
import { User } from "better-auth";

sendResetPassword: async ({ user, token }) => {
const resetLink = `${process.env.APP_URL}/reset-password?token=${token}`;
const u = user as User & { locale: Locale };
const userLocale = u.locale || "en";
await emailOrchestrator.sendAndLogForgotEmail({
to: user.email,
url: resetLink,
userId: user.id,
locale: userLocale,
});
},
import { User } from "better-auth";

sendResetPassword: async ({ user, token }) => {
const resetLink = `${process.env.APP_URL}/reset-password?token=${token}`;
const u = user as User & { locale: Locale };
const userLocale = u.locale || "en";
await emailOrchestrator.sendAndLogForgotEmail({
to: user.email,
url: resetLink,
userId: user.id,
locale: userLocale,
});
},

Did you find this page helpful?