Trouble inferring types on client side (1.3.4)

@Better Auth Hey, I was trying to infer some types on client side: type AuthContextValue = { member: typeof authClient.$Infer.Member | null; user: typeof authClient.$Infer.Session.user | null; session: typeof authClient.$Infer.Session.session | null; activeOrganization: typeof authClient.$Infer.ActiveOrganization | null; } export const authClient = createAuthClient({ baseURL: env.VITE_BASE_URL, plugins: [ adminClient(), organizationClient({ allowUserToCreateOrganization: true, cancelPendingInvitationsOnReInvite: true, invitationLimit: 1, organizationDeletion: { disabled: true, }, teams: { enabled: false, }, }), phoneNumberClient(), emailOTPClient(), inferAdditionalFields({ user: { role: { type: "string", }, phoneNumber: { type: "string", required: true, input: true, unique: true, }, referralCode: { type: "string", required: true, input: true, }, }, }), ], }) This is my auth-client.ts I have an error here activeOrganization: typeof authClient.$Infer.ActiveOrganization | null; and also here member: typeof authClient.$Infer.Member | null; Property 'Member' does not exist on type '{ Session: { user: { id: string; email: string; emailVerified: boolean; name: string; createdAt: Date; updatedAt: Date; image?: string | null | undefined; }; session: { id: string; userId: string; ... 5 more ...; userAgent?: string | ... 1 more ... | undefined; }; }; }'.ts(2339). Property 'ActiveOrganization' does not exist on type '{ Session: { user: { id: string; email: string; emailVerified: boolean; name: string; createdAt: Date; updatedAt: Date; image?: string | null | undefined; }; session: { id: string; userId: string; ... 5 more ...; userAgent?: string | ... 1 more ... | undefined; }; }; }'.ts(2339)
15 Replies
Better Auth
Better Auth4w ago
It looks like the error appears because your current Better Auth client isn’t exposing the types for Member and ActiveOrganization on its $Infer object. In Better Auth, types like ActiveOrganization and Member are only added to the inference if the corresponding plugin (and its proper schema) is registered on the server and then passed to the client through functions like inferAdditionalFields or with a dedicated organization client setup [3]. A few things to check or try: 1. Verify that on the server side you’ve configured the organization plugin to include additional fields (and a member extension if applicable). The inference for ActiveOrganization (and its related types) is only added when the server configuration exposes it. If your server config does not include those aspects, the client’s $Infer object won’t have them. 2. Ensure that on the client you are using the proper organization client plugin (and if needed, an additional helper like inferOrgAdditionalFields) so that the client is aware of the server’s extended types. See the guidelines on inferring additional fields from the organization plugin [7]. 3. If you’re sure your server-side config is correct, check if you might need to update (or re-import) your type definitions from the organization plugin. Sometimes, the $Infer object is limited to only what the plugins make available. In this case, if Member isn’t exported by the plugin you’re using, you may want to use the types that come with the organization plugin directly or extend your own definitions. In summary, the error stems from the fact that Better Auth doesn’t expose “Member” or “ActiveOrganization” on $Infer by default—it depends on how the plugins are configured and inferred from the server. Double-check your server config
GitHub
better-auth/better-auth
The most comprehensive authentication framework for TypeScript - better-auth/better-auth
Better Auth
Better Auth4w ago
GitHub
better-auth/better-auth
The most comprehensive authentication framework for TypeScript - better-auth/better-auth
GitHub
better-auth/better-auth
The most comprehensive authentication framework for TypeScript - better-auth/better-auth
GitHub
Type mismatch authClient Active Organization · Issue #2285 · bett...
Is this suited for github? Yes, this is suited for github To Reproduce Mismatch between the type returned by authClient.useActiveOrganization and typeof authClient.$Infer.ActiveOrganization export ...
TypeScript | Better Auth
Better Auth TypeScript integration.
GitHub
Organization additional fields not returning new fields · Issue #3...
Is this suited for github? Yes, this is suited for github To Reproduce To reproduce, just use my configuration down below and try get the field publicId on the data returned by useActiveOrganizatio...
Hakai
HakaiOP4w ago
@Better Auth here's the full auth-client.ts file import { createAuthClient } from "better-auth/react" import { adminClient, inferAdditionalFields, organizationClient, phoneNumberClient, emailOTPClient, } from "better-auth/client/plugins" import env from "./env" export const authClient = createAuthClient({ baseURL: env.VITE_BASE_URL, plugins: [ adminClient(), organizationClient({ allowUserToCreateOrganization: true, cancelPendingInvitationsOnReInvite: true, invitationLimit: 1, organizationDeletion: { disabled: true, }, teams: { enabled: false, }, }), phoneNumberClient(), emailOTPClient(), inferAdditionalFields({ user: { role: { type: "string", }, phoneNumber: { type: "string", required: true, input: true, unique: true, }, referralCode: { type: "string", required: true, input: true, }, }, }), ], })
Better Auth
Better Auth4w ago
Your auth‐client.ts configuration looks well set up! You're using several key plugins—adminClient, organizationClient, phoneNumberClient, emailOTPClient, and inferAdditionalFields—which is in line with the typical Better Auth client setup [4]. A couple of things to keep in mind: • With the organizationClient options, you’ve configured settings like allowing user creation of organizations, cancelling pending invitations on re-invite, and disabling organization deletion. This setup is consistent with our organization plugin best practices [6]. • For inferAdditionalFields, you’re manually specifying the user additional fields (role, phoneNumber, referralCode). This is a good practice—especially if your server/client projects are separate—to ensure type inference without exposing unneeded server details [9]. Overall, everything appears to be correctly configured. If you run into any issues (especially around type inference or field exposure), double-check that the additional field definitions on your client match the server configuration. Otherwise, your client file looks ready to roll! Sources: [4] Client | Better Auth [6] Organization | Better Auth [9] TypeScript | Better Auth
Client | Better Auth
Better Auth client library for authentication.
Organization | Better Auth
The organization plugin allows you to manage your organization's members and teams.
Hakai
HakaiOP4w ago
@Better Auth On point no.2 Do i add the inferOrgAdditionalFields inside inferAdditionalFields or is it it's own plugin? Could you show me an example since im not in a mono repo and cant use something line <typeof auth> to infer additional fields
Better Auth
Better Auth4w ago
You're going to want to use inferOrgAdditionalFields as its own plugin rather than nesting it inside inferAdditionalFields. Since you're not in a monorepo and can't rely on referencing your server auth object via a generic (like <typeof auth>), you can call inferOrgAdditionalFields without that generic parameter. For example, if you're setting up your client config, your code might look like this:
import { createAuthClient } from "better-auth/client";
import { organizationClient, inferOrgAdditionalFields } from "better-auth/client/plugins";

const authClient = createAuthClient({
plugins: [
organizationClient({
teams: { enabled: true },
schema: inferOrgAdditionalFields() // using the plugin by itself
}),
// You can also include inferAdditionalFields for user-specific fields if needed.
],
});
import { createAuthClient } from "better-auth/client";
import { organizationClient, inferOrgAdditionalFields } from "better-auth/client/plugins";

const authClient = createAuthClient({
plugins: [
organizationClient({
teams: { enabled: true },
schema: inferOrgAdditionalFields() // using the plugin by itself
}),
// You can also include inferAdditionalFields for user-specific fields if needed.
],
});
This example shows that inferOrgAdditionalFields is applied directly inside the organization client plugin configuration and isn’t nested within inferAdditionalFields [8]. This setup is ideal when you're not able to use the generic type reference from your server auth configuration. Sources: [8] docs(org): inferOrgAdditionalFields has wrong import path
GitHub
Build software better, together
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.
From An unknown user
From An unknown user
From An unknown user
GitHub
docs(org): inferOrgAdditionalFields has wrong import path by ping...
The newly introduced inferOrgAdditionalFields has the wrong import path in the docs. Closes #3733 Summary by cubic Fixed the import path for inferOrgAdditionalFields in the organization plugin do...
Hakai
HakaiOP4w ago
@Better Auth This is my server side config auth.ts organization({ allowUserToCreateOrganization: async ({ id }) => { return await isUserOrgOwner(id); }, cancelPendingInvitationsOnReInvite: true, invitationLimit: 1, organizationDeletion: { disabled: true, }, teams: { enabled: false, }, }), I am still not able to get the types inferred on client side using my current auth-client.ts setup. What should I do?
Better Auth
Better Auth4w ago
It looks like your client isn’t picking up the organization plugin’s types because the client setup isn’t correctly wired to your server’s auth type. To fix this, ensure that on the client side you’re using the dedicated organization client plugin and passing your server-side auth instance as a type parameter. For example, adjust your auth‐client.ts like so:
import { createAuthClient } from "better-auth/client";
import { organizationClient } from "better-auth/client/plugins";
import type { auth } from "./auth";

export const authClient = createAuthClient({
plugins: [ organizationClient<typeof auth>() ]
});
import { createAuthClient } from "better-auth/client";
import { organizationClient } from "better-auth/client/plugins";
import type { auth } from "./auth";

export const authClient = createAuthClient({
plugins: [ organizationClient<typeof auth>() ]
});
This approach tells the client plugin exactly what types to expect, ensuring that the inferred types (including the organization‑specific ones) are available on the client side [2][3]. Also verify that your TypeScript configuration has strict mode enabled because Better Auth is designed to work optimally with strict type inference [3]. Sources: [2] Organization | Better Auth [3] TypeScript | Better Auth
Organization | Better Auth
The organization plugin allows you to manage your organization's members and teams.
TypeScript | Better Auth
Better Auth TypeScript integration.
Hakai
HakaiOP4w ago
@Better Auth Since i'm not on a mono repo I cant use <typeof auth>
Better Auth
Better Auth4w ago
You're correct—when your client and server are in separate projects, the approach using <typeof auth> (which automatically infers the additional fields) isn’t applicable. In that case, the recommendation is to manually specify your additional field definitions in your client-side configuration. This approach ensures you only expose what’s necessary, helping to avoid inadvertently leaking server-side details [8]. For example, instead of writing:
import { inferAdditionalFields } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";
import type { auth } from "./auth";

export const authClient = createAuthClient({
plugins: [inferAdditionalFields<typeof auth>()],
});
import { inferAdditionalFields } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";
import type { auth } from "./auth";

export const authClient = createAuthClient({
plugins: [inferAdditionalFields<typeof auth>()],
});
You would manually define the fields like so:
import { inferAdditionalFields } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";

export const authClient = createAuthClient({
plugins: [inferAdditionalFields({ user: { role: { type: "string" /* add other field options as needed */ } } })],
});
import { inferAdditionalFields } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";

export const authClient = createAuthClient({
plugins: [inferAdditionalFields({ user: { role: { type: "string" /* add other field options as needed */ } } })],
});
This way, you maintain type safety without relying on server-only type inference in a non-monorepo setup [8]. Sources: [8] TypeScript | Better Auth
TypeScript | Better Auth
Better Auth TypeScript integration.
Hakai
HakaiOP4w ago
@Better Auth One more quick question, when sending an invitation. Is it possible to also extend the invitation schema to include the organizationName, organizationSlug and inviterName?
Better Auth
Better Auth4w ago
Yes, you can extend the invitation schema to include additional fields like organizationName, organizationSlug, and inviterName. Starting with Better Auth v1.3, you can use the additionalFields option in your organization plugin configuration to add custom fields to the invitation model. This means you can specify these extra fields in your configuration, and they will be automatically included in both the API request and response payloads, helping you tailor the schema to your application's needs [2], [17]. Sources: [2] Organization | Better Auth [17] feat(org): additionalFields for org, member, invitation & team
GitHub
Build software better, together
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.
From An unknown user
From An unknown user
From An unknown user
Organization | Better Auth
The organization plugin allows you to manage your organization's members and teams.
GitHub
feat(org): additionalFields for org, member, invitation & team by p...
docs tests Summary by cubic Added support for custom additionalFields on organization, member, invitation, and team models, allowing users to define extra fields in the organization plugin schem...
Hakai
HakaiOP4w ago
@Better Auth Could you show me an example of how I can add the org name and inviter name when sending an invite in the db? I don't want to just add it to the email but also to the db.
Better Auth
Better Auth4w ago
Below is one way to do this. The idea is to extend the invitation record in your database to store extra fields (for example, organizationName and inviterName) and then update those fields when sending the invitation. For instance, you could extend your Better Auth configuration to add additional fields to the invitation schema. Then, in your custom sendInvitationEmail function, after sending the email, you update (or create) the invitation record with these extra properties. Here's an example: ``ts import { betterAuth } from "better-auth"; import { organization } from "better-auth/plugins"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { sendOrganizationInvitation } from "./email"; import db from "./db"; // your database instance export const auth = betterAuth({ database: drizzleAdapter(db, { provider: "pg" }), schema: { // Extend the invitation schema to include extra fields invitation: { additionalFields: { organizationName: { type: "string" }, inviterName: { type: "string" } } }, // ... you can extend other models as needed }, plugins: [ organization({ async sendInvitationEmail(data) { const inviteLink = https://example.com/accept-invitation/${data.id}`;
// Send the invitation email await sendOrganizationInvitation({ email: data.email, invitedByUsername: data.inviter.user.name, teamName: data.organization.name, inviteLink, });
// Now update the invitation record in the database // This assumes your invitation record has been set up with additionalFields await db.update({ model: "invitation", where: { id: data.id }, update: { organizationName: data.organization.name, inviterName: data.inviter.user.name
Better Auth
Better Auth4w ago
} }); }, }), ], }); ``` In this example:
1. We extend the invitation schema by providing two additional fields—organizationName and inviterName. This lets Better Auth know to expect and store these values [1].
2. In the custom sendInvitationEmail implementation, after sending the email, the code calls your database adapter’s update method to store the extra data. This way, the invitation record contains both the original invitation data and your custom fields [1], [11]. This approach adheres to Better Auth’s extensibility principles while leveraging your existing adapter (see also the discussion on extending fields in the original organization invitation examples [1]). Feel free to adjust the implementation to fit your specific database adapter or hook setup. Sources: [1] Organization | Better Auth [11] Database | Better Auth
Organization | Better Auth
The organization plugin allows you to manage your organization's members and teams.

Did you find this page helpful?