Help: banUser expects string userId but my DB uses number — what's the best way to handle this?
Hey folks 👋
I’m using authClient.admin.banUser from BetterAuth like this:
const bannedUser = await authClient.admin.banUser({
userId: "user_id_here", // string
banReason: "Spamming",
banExpiresIn: 60 * 60 * 24 * 7, // 7 days
});
In my DB schema (using Drizzle), the user.id is a number, not a string. So I’m running into a type mismatch here. The method expects a string for userId, and the returned data is typed as any. Even if I do bannedUser as User, the id still ends up being a string, which causes issues when using it elsewhere with number-based types.
I’m wondering:
Is it okay to just cast userId.toString() when calling this and manually cast it back to number afterward?
Or is this a sign that I should skip this helper method and just handle the ban logic myself at the DB level, with an authorization check before running the mutation?
Also, is there a way to make BetterAuth return a properly typed result?
Would really appreciate how others are handling this — thanks!2 Replies
You'll have to configure better-auth to support numeric IDs, but this will also mean all other tables that's linked to Better Auth will have to use numeric IDs too.
To do this you must head into your auth config and set
advanced.database.useNumericId
to true.
With this, it also means that you must handle ID generation (most cases it's auto-incrementing numeric IDs).
Everything relating to validation and typings will remain using a string, but you can safely enter a string version of the number id and everything will be safely translated back to a number when Better-auth interacts with your DBThanks for the explanation!
I’ve already enabled numeric IDs in my config:
advanced: {
database: {
generateId: false,
useNumberId: true,
},
},
But my issue is mostly around typings. When I call:
const bannedUser = await authClient.admin.banUser({ ... });
The returned type is:
const bannedUser: Data<{ user: any }> | Error$1<{ code?: string; message?: string; }>
So the user inside it is typed as any. Even if I cast it like this:
bannedUser.data.user as User
The user.id still ends up being a string. For setting up tanstack queryKey after banning ['user', bannedUser.id]
. This sets the queryKey as ['user', '69']
instead of ['user', 69]
Also, shouldn't the API accept a numeric userId since useNumberId is enabled? Or is it still expected to pass a string version of the ID?
I was under the impression that BetterAuth was fully type-safe, but right now I’m having to cast things manually, and it doesn’t seem to fully respect the numeric types from my DB schema.
At this point, would it be better to skip the helper methods and just use my own DB operations with an auth check?
Would appreciate any clarity on how this is usually handled 🙏