[GH-ISSUE #7039] TypeScript inference fails with organizationClient when additionalFields is used #10711

Open
opened 2026-04-13 07:01:05 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @toshmukhamedov on GitHub (Dec 28, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/7039

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Create a client using createAuthClient() including organizationClient() plugin.
  2. Set the following in tsconfig.json:
{
  "declaration": true,
  "moduleResolution": "bundler"
}
  1. Use the following client configuration:
export const authClient = createAuthClient({
  baseURL: import.meta.env.VITE_API_URL,
  basePath: "/api/user/auth",
  plugins: [
    adminClient(),
    organizationClient({
      teams: { enabled: true },
      schema: {
        organization: {
          additionalFields: {
            publicId: {
              type: "string",
              input: false,
            },
          },
        },
      },
    }),
  ],
});

Current vs. Expected behavior

Current:
TypeScript throws the following error: The inferred type of authClient cannot be named without a reference to ../../node_modules/better-auth/dist/index-BZSqJoCN.mjs. This is likely not portable. A type annotation is necessary. (ts 2742)

Expected:
TypeScript should correctly infer the type of authClient without requiring a manual type annotation.

What version of Better Auth are you using?

1.4.9

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 25.2.0: Tue Nov 18 21:09:45 PST 2025; root:xnu-12377.61.12~1/RELEASE_ARM64_T6030",
    "release": "25.2.0",
    "cpuCount": 11,
    "cpuModel": "Apple M3 Pro",
    "totalMemory": "18.00 GB",
    "freeMemory": "0.19 GB"
  },
  "node": {
    "version": "v22.20.0",
    "env": "development"
  },
  "packageManager": {
    "name": "pnpm",
    "version": "10.22.0"
  },
  "frameworks": [
    {
      "name": "react",
      "version": "^19.2.0"
    }
  ],
  "databases": null,
  "betterAuth": {
    "version": "Unknown",
    "config": null,
    "error": "fetch failed"
  }
}

Which area(s) are affected? (Select all that apply)

Client

Auth config (if applicable)

export const authClient = createAuthClient({
  baseURL: import.meta.env.VITE_API_URL,
  basePath: "/api/user/auth",
  plugins: [
    adminClient(),
    organizationClient({
      teams: {
        enabled: true,
      },
      schema: {
        organization: {
          additionalFields: {
            publicId: {
              type: "string",
              input: false,
            },
          },
        },
      },
    }),
  ],
});

Additional context

When using organizationClient() with the additionalFields option, TypeScript fails to infer the type of authClient under declaration: true and moduleResolution: "bundler".

This is similar to the previously reported issue #6565, but now it only occurs when additionalFields are specified in the plugin schema.

Originally created by @toshmukhamedov on GitHub (Dec 28, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/7039 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Create a client using createAuthClient() including organizationClient() plugin. 2. Set the following in tsconfig.json: ```json { "declaration": true, "moduleResolution": "bundler" } ``` 3. Use the following client configuration: ```ts export const authClient = createAuthClient({ baseURL: import.meta.env.VITE_API_URL, basePath: "/api/user/auth", plugins: [ adminClient(), organizationClient({ teams: { enabled: true }, schema: { organization: { additionalFields: { publicId: { type: "string", input: false, }, }, }, }, }), ], }); ``` ### Current vs. Expected behavior Current: TypeScript throws the following error: `The inferred type of authClient cannot be named without a reference to ../../node_modules/better-auth/dist/index-BZSqJoCN.mjs. This is likely not portable. A type annotation is necessary. (ts 2742)` Expected: TypeScript should correctly infer the type of authClient without requiring a manual type annotation. ### What version of Better Auth are you using? 1.4.9 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 25.2.0: Tue Nov 18 21:09:45 PST 2025; root:xnu-12377.61.12~1/RELEASE_ARM64_T6030", "release": "25.2.0", "cpuCount": 11, "cpuModel": "Apple M3 Pro", "totalMemory": "18.00 GB", "freeMemory": "0.19 GB" }, "node": { "version": "v22.20.0", "env": "development" }, "packageManager": { "name": "pnpm", "version": "10.22.0" }, "frameworks": [ { "name": "react", "version": "^19.2.0" } ], "databases": null, "betterAuth": { "version": "Unknown", "config": null, "error": "fetch failed" } } ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript export const authClient = createAuthClient({ baseURL: import.meta.env.VITE_API_URL, basePath: "/api/user/auth", plugins: [ adminClient(), organizationClient({ teams: { enabled: true, }, schema: { organization: { additionalFields: { publicId: { type: "string", input: false, }, }, }, }, }), ], }); ``` ### Additional context When using `organizationClient()` with the `additionalFields` option, TypeScript fails to infer the type of authClient under `declaration: true` and `moduleResolution: "bundler"`. This is similar to the previously reported issue #6565, but now it only occurs when `additionalFields` are specified in the plugin schema.
GiteaMirror added the bugorganization labels 2026-04-13 07:01:05 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Dec 28, 2025):

It appears you are experiencing a TypeScript inference issue when using the organizationClient with additionalFields. This is a known concern related to TypeScript not correctly inferring types when specific configurations are applied, especially under declaration: true and moduleResolution: "bundler" settings.

You might want to try the following troubleshooting steps:

  1. Ensure you are using the latest version of Better Auth. There have been fixes related to TypeScript inference issues in previous updates.
  2. You can try adding explicit type annotations to the authClient if TypeScript is still throwing inference errors. For example:
    const authClient: YourExpectedType = createAuthClient({ /* ... */ });
    
  3. Consider reviewing your TypeScript configurations to ensure there isn't anything conflicting with the inference process.

This issue seems to be close to some previously reported cases, such as #6565, wherein similar experiences were noted.

Lastly, if the problem persists, it might be beneficial to tag @bekacru or @ping__ in your follow-up for further assistance from the Better Auth team.

Have you tried any of these steps, or do you need help with specific information on adjusting your configurations?

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3694521644 --> @better-auth-agent[bot] commented on GitHub (Dec 28, 2025): It appears you are experiencing a TypeScript inference issue when using the `organizationClient` with `additionalFields`. This is a known concern related to TypeScript not correctly inferring types when specific configurations are applied, especially under `declaration: true` and `moduleResolution: "bundler"` settings. You might want to try the following troubleshooting steps: 1. Ensure you are using the latest version of Better Auth. There have been fixes related to TypeScript inference issues in previous updates. 2. You can try adding explicit type annotations to the `authClient` if TypeScript is still throwing inference errors. For example: ```typescript const authClient: YourExpectedType = createAuthClient({ /* ... */ }); ``` 3. Consider reviewing your TypeScript configurations to ensure there isn't anything conflicting with the inference process. This issue seems to be close to some previously reported cases, such as #6565, wherein similar experiences were noted. Lastly, if the problem persists, it might be beneficial to tag @bekacru or @ping__ in your follow-up for further assistance from the Better Auth team. Have you tried any of these steps, or do you need help with specific information on adjusting your configurations? _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

@dosubot[bot] commented on GitHub (Dec 28, 2025):

This is a known TypeScript limitation with complex generics and plugin schemas in better-auth, especially when using declaration: true and moduleResolution: "bundler". The error happens because TypeScript tries to infer types that reference internal/private types from better-auth, which aren't exported as public types, making the inferred type non-portable in declaration files. This is why the error only appears when you use additionalFields in the plugin schema [details].

Recent updates (including PR #6643, merged 2025-12-10) fixed some inference issues by wrapping the plugin options with a NoInfer utility type, which helps prevent TypeScript from inferring overly complex types that cause these errors [PR #6643]. If you are on 1.4.9 or later, you should have these fixes, but some edge cases may persist depending on your tsconfig and how you structure your schema.

Workarounds that are known to help:

  • Use the inferOrgAdditionalFields utility when passing the schema to organizationClient. This helps TypeScript infer the type in a more portable way and can avoid TS2742 in some setups. Example:
    import { inferOrgAdditionalFields, organizationClient } from "better-auth/client/plugins";
    import type { auth } from "./auth"; // your server-side auth config
    
    export const authClient = createAuthClient({
      // ...
      plugins: [
        adminClient(),
        organizationClient({
          teams: { enabled: true },
          schema: inferOrgAdditionalFields<typeof auth>(),
        }),
      ],
    });
    
  • If your client and server are in separate projects, manually duplicate the organization schema and use inferOrgAdditionalFields({ organization: { additionalFields: ... } }) [example].
  • If you don't need .d.ts files, set declaration: false and declarationMap: false in your tsconfig.
  • Set exactOptionalPropertyTypes: false in your tsconfig (this can reduce type strictness).
  • As a last resort, use an explicit type annotation like as ReturnType<typeof createAuthClient> to suppress the error, but you may lose plugin-specific typings.

This is a known limitation, and most users with strict TypeScript settings and declaration enabled use one of these workarounds until a more robust type export system is implemented [reference].

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3694523526 --> @dosubot[bot] commented on GitHub (Dec 28, 2025): <!-- Answer --> This is a known TypeScript limitation with complex generics and plugin schemas in better-auth, especially when using `declaration: true` and `moduleResolution: "bundler"`. The error happens because TypeScript tries to infer types that reference internal/private types from better-auth, which aren't exported as public types, making the inferred type non-portable in declaration files. This is why the error only appears when you use `additionalFields` in the plugin schema [[details](https://github.com/better-auth/better-auth/issues/6565)]. Recent updates (including PR #6643, merged 2025-12-10) fixed some inference issues by wrapping the plugin options with a `NoInfer` utility type, which helps prevent TypeScript from inferring overly complex types that cause these errors [[PR #6643](https://github.com/better-auth/better-auth/pull/6643)]. If you are on 1.4.9 or later, you should have these fixes, but some edge cases may persist depending on your tsconfig and how you structure your schema. Workarounds that are known to help: - Use the `inferOrgAdditionalFields` utility when passing the schema to `organizationClient`. This helps TypeScript infer the type in a more portable way and can avoid TS2742 in some setups. Example: ```ts import { inferOrgAdditionalFields, organizationClient } from "better-auth/client/plugins"; import type { auth } from "./auth"; // your server-side auth config export const authClient = createAuthClient({ // ... plugins: [ adminClient(), organizationClient({ teams: { enabled: true }, schema: inferOrgAdditionalFields<typeof auth>(), }), ], }); ``` - If your client and server are in separate projects, manually duplicate the organization schema and use `inferOrgAdditionalFields({ organization: { additionalFields: ... } })` [[example](https://github.com/better-auth/better-auth/pull/3612)]. - If you don't need `.d.ts` files, set `declaration: false` and `declarationMap: false` in your tsconfig. - Set `exactOptionalPropertyTypes: false` in your tsconfig (this can reduce type strictness). - As a last resort, use an explicit type annotation like `as ReturnType<typeof createAuthClient>` to suppress the error, but you may lose plugin-specific typings. This is a known limitation, and most users with strict TypeScript settings and declaration enabled use one of these workarounds until a more robust type export system is implemented [[reference](https://github.com/better-auth/better-auth/issues/6565)]. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/052c613a-0ae4-4b8d-86c7-0b9fc2a3b8da?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/052c613a-0ae4-4b8d-86c7-0b9fc2a3b8da?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/052c613a-0ae4-4b8d-86c7-0b9fc2a3b8da?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/052c613a-0ae4-4b8d-86c7-0b9fc2a3b8da?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/052c613a-0ae4-4b8d-86c7-0b9fc2a3b8da?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/052c613a-0ae4-4b8d-86c7-0b9fc2a3b8da?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/052c613a-0ae4-4b8d-86c7-0b9fc2a3b8da?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20is%20a%20known%20TypeScript%20limitation%20with%20complex%20generics%20and%20plugin%20schemas%20in%20better-auth%2C%20especially%20when%20using%20%60declaration%3A%20true%60%20and%20%60moduleResolution%3A%20%22bundler%22%60.%20The%20error%20happens%20because%20TypeScript%20tries%20to%20infer%20types%20that%20reference%20internal/private%20types%20from%20better-auth%2C%20which%20aren%27t%20exported%20as%20public%20types%2C%20making%20the%20inferred%20type%20non-portable%20in%20declaration%20files.%20This%20is%20why%20the%20error%20only%20appears%20when%20you%20use%20%60additionalFields%60%20in%20the%20plugin%20schema%20%5B%5Bdetails%5D%28https%3A//github.com/better-auth/better-auth/issues/6565%29%5D.%0A%0ARecent%20updates%20%28including%20PR%20%236643%2C%20merged%202025-12-10%29%20fixed%20some%20inference%20issues%20by%20wrapping%20the%20plugin%20options%20with%20a%20%60NoInfer%60%20utility%20type%2C%20which%20helps%20prevent%20TypeScript%20from%20inferring%20overly%20complex%20types%20that%20cause%20these%20errors%20%5B%5BPR%20%236643%5D%28https%3A//github.com/better-auth/better-auth/pull/6643%29%5D.%20If%20you%20are%20on%201.4.9%20or%20later%2C%20you%20should%20have%20these%20fixes%2C%20but%20some%20edge%20cases%20may%20persist%20depending%20on%20your%20tsconfig%20and%20how%20you%20structure%20your%20schema.%0A%0AWorkarounds%20that%20are%20known%20to%20help%3A%0A-%20Use%20the%20%60inferOrgAdditionalFields%60%20utility%20when%20passing%20the%20schema%20to%20%60organizationClient%60.%20This%20helps%20TypeScript%20infer%20the%20type%20in%20a%20more%20portable%20way%20and%20can%20avoid%20TS2742%20in%20some%20setups.%20Example%3A%0A%20%20%60%60%60ts%0A%20%20import%20%7B%20inferOrgAdditionalFields%2C%20organizationClient%20%7D%20from%20%22better-auth/client/plugins%22%3B%0A%20%20import%20type%20%7B%20auth%20%7D%20from%20%22./auth%22%3B%20//%20your%20server-side%20auth%20config%0A%0A%20%20export%20const%20authClient%20%3D%20createAuthClient%28%7B%0A%20%20%20%20//%20...%0A%20%20%20%20plugins%3A%20%5B%0A%20%20%20%20%20%20adminClient%28%29%2C%0A%20%20%20%20%20%20organizationClient%28%7B%0A%20%20%20%20%20%20%20%20teams%3A%20%7B%20enabled%3A%20true%20%7D%2C%0A%20%20%20%20%20%20%20%20schema%3A%20inferOrgAdditionalFields%3Ctypeof%20auth%3E%28%29%2C%0A%20%20%20%20%20%20%7D%29%2C%0A%20%20%20%20%5D%2C%0A%20%20%7D%29%3B%0A%20%20%60%60%60%0A-%20If%20your%20client%20and%20server%20are%20in%20separate%20projects%2C%20manually%20duplicate%20the%20organization%20schema%20and%20use%20%60inferOrgAdditionalFields%28%7B%20organization%3A%20%7B%20additionalFields%3A%20...%20%7D%20%7D%29%60%20%5B%5Bexample%5D%28https%3A//github.com/better-auth/better-auth/pull/3612%29%5D.%0A-%20If%20you%20don%27t%20need%20%60.d.ts%60%20files%2C%20set%20%60declaration%3A%20false%60%20and%20%60declarationMap%3A%20false%60%20in%20your%20tsconfig.%0A-%20Set%20%60exactOptionalPropertyTypes%3A%20false%60%20in%20your%20tsconfig%20%28this%20can%20reduce%20type%20strictness%29.%0A-%20As%20a%20last%20resort%2C%20use%20an%20explicit%20type%20annotation%20like%20%60as%20ReturnType%3Ctypeof%20createAuthClient%3E%60%20to%20suppress%20the%20error%2C%20but%20you%20may%20lose%20plugin-specific%20typings.%0A%0AThis%20is%20a%20known%20limitation%2C%20and%20most%20users%20with%20strict%20TypeScript%20settings%20and%20declaration%20enabled%20use%20one%20of%20these%20workarounds%20until%20a%20more%20robust%20type%20export%20system%20is%20implemented%20%5B%5Breference%5D%28https%3A//github.com/better-auth/better-auth/issues/6565%29%5D.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/7039)
Author
Owner

@SamJbori commented on GitHub (Dec 30, 2025):

I am facing a similar issue when I use anonymous and/or captcha plugins in 1.4.8+, 1.4.7 was fine,

The inferred type of 'initAuth' cannot be named without a reference to '../../node_modules/better-auth/dist/plugins/anonymous/types.mjs'. This is likely not portable. A type annotation is necessary.ts(2742)
The inferred type of 'initAuth' cannot be named without a reference to '../../node_modules/better-auth/dist/plugins/captcha/types.mjs'. This is likely not portable. A type annotation is necessary.ts(2742)

My current solution is to infer type

    plugins: [
      anonymous({
       ...settings
      }),
      captcha({
        ...settings
      }),
    ] as BetterAuthOptions["plugins"],

I've had a history of struggling with types after upgrade, in 1.4.0 I had the issue with infering session, I resolved it with

export type Auth = ReturnType<typeof initAuth>;
export type Session = InferSession<Auth>;
export type User = InferUser<Auth>;
export type AuthData = {
  session: Session;
  user: User;
} | null;

I consider these minor inconveniences, but nevertheless annoying ones that does interrupt building and linting, not sure how high it's on the priority list, but hopefully 🤞🤞 I don't have to deal with them ever again.

<!-- gh-comment-id:3699242206 --> @SamJbori commented on GitHub (Dec 30, 2025): I am facing a similar issue when I use `anonymous` and/or `captcha` plugins in `1.4.8`+, `1.4.7` was fine, ```bash The inferred type of 'initAuth' cannot be named without a reference to '../../node_modules/better-auth/dist/plugins/anonymous/types.mjs'. This is likely not portable. A type annotation is necessary.ts(2742) The inferred type of 'initAuth' cannot be named without a reference to '../../node_modules/better-auth/dist/plugins/captcha/types.mjs'. This is likely not portable. A type annotation is necessary.ts(2742) ``` My current solution is to infer type ```typescript plugins: [ anonymous({ ...settings }), captcha({ ...settings }), ] as BetterAuthOptions["plugins"], ``` I've had a history of struggling with types after upgrade, in `1.4.0` I had the issue with infering session, I resolved it with ```typescript export type Auth = ReturnType<typeof initAuth>; export type Session = InferSession<Auth>; export type User = InferUser<Auth>; export type AuthData = { session: Session; user: User; } | null; ``` I consider these minor inconveniences, but nevertheless annoying ones that does interrupt building and linting, not sure how high it's on the priority list, but hopefully 🤞🤞 I don't have to deal with them ever again.
Author
Owner

@tkimia commented on GitHub (Apr 9, 2026):

organizationClient needs the server schema passed explicitly for type inference to work. Use inferOrgAdditionalFields alongside inferAdditionalFields:

import {
  inferAdditionalFields,
  inferOrgAdditionalFields,
  organizationClient,
} from "better-auth/client/plugins"

export const authClient = createAuthClient({
  plugins: [
    inferAdditionalFields<typeof auth>(),
    organizationClient({
      schema: inferOrgAdditionalFields<typeof auth>(),
      // ...other options (ac, roles, teams, etc.)
    }),
  ],
})

inferAdditionalFields only bridges user and session fields — it doesn't touch organization schema. inferOrgAdditionalFields does the equivalent for organization, member, invitation, and team additional fields.

After this, useActiveOrganization(), useListOrganizations(), etc. will include your additionalFields in their return types without any casts.

<!-- gh-comment-id:4217788684 --> @tkimia commented on GitHub (Apr 9, 2026): `organizationClient` needs the server schema passed explicitly for type inference to work. Use `inferOrgAdditionalFields` alongside `inferAdditionalFields`: ```ts import { inferAdditionalFields, inferOrgAdditionalFields, organizationClient, } from "better-auth/client/plugins" export const authClient = createAuthClient({ plugins: [ inferAdditionalFields<typeof auth>(), organizationClient({ schema: inferOrgAdditionalFields<typeof auth>(), // ...other options (ac, roles, teams, etc.) }), ], }) ``` `inferAdditionalFields` only bridges `user` and `session` fields — it doesn't touch organization schema. `inferOrgAdditionalFields` does the equivalent for `organization`, `member`, `invitation`, and `team` additional fields. After this, `useActiveOrganization()`, `useListOrganizations()`, etc. will include your `additionalFields` in their return types without any casts.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#10711