[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
nikatune4mo ago
did u inferred it to auth-client.ts file?
ddev
ddevOP4mo ago
no i didnt, let me try it
nikatune
nikatune4mo ago
thats why sir
ddev
ddevOP4mo 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
Ping4mo 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
ddevOP4mo 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?