dist/index.d.mts re-exports entire zod namespace, causing import("better-auth").$strip in downstream declaration emit #2872

Closed
opened 2026-03-13 10:24:58 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @aurelientanguy on GitHub (Feb 14, 2026).

Originally assigned to: @himself65 on GitHub.

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Set up a TypeScript monorepo with declaration emit (emitDeclarationOnly: true)
  2. Create a package (e.g. packages/auth) that depends on better-auth and exports an Auth type derived from betterAuth()
  3. Create a second package (e.g. packages/api) that imports the Auth type and also uses Zod schemas (directly or via drizzle-zod)
  4. Create a consuming app (e.g. apps/app) that depends on packages/api but does not directly depend on better-auth
  5. Run tsc --emitDeclarationOnly on packages/api
  6. Observe the emitted .d.ts files — ZodObject generic parameters resolve as import("better-auth").$strip instead of import("zod/v4/core").$strip
  7. When apps/app type-checks against these declarations, import("better-auth") is unresolvable (since better-auth is not a direct or hoisted dependency), causing types to collapse to any

Current vs. Expected behavior

Current

better-auth@1.4.18's dist/index.d.mts (lines 27, 29–30) contains wildcard re-exports of the entire Zod namespace:

export * from "zod";
export * from "zod/v4/core";
export * from "zod/v4";

This makes every Zod type accessible via import("better-auth") — including internal types like $strip, $ZodTypeInternals, etc.

When TypeScript's declaration emitter encounters Zod types (like the $strip second generic parameter of ZodObject), it picks the "shortest accessible module path." Since better-auth re-exports zod/v4/core, TypeScript resolves $strip as import("better-auth").$strip instead of import("zod/v4/core").$strip.

Downstream consumers that don't have better-auth as a direct dependency then fail type-checking — the unresolvable import("better-auth").$strip causes types to collapse to any:

error TS7006: Parameter 'feature' implicitly has an 'any' type.

Expected

better-auth should not re-export zod, zod/v4, and zod/v4/core from its public API surface. These wildcard re-exports leak internal implementation details into TypeScript's module resolution graph for all downstream consumers.

Removing lines 27, 29–30 from dist/index.d.mts would fix the issue — TypeScript would then resolve $strip through zod/v4/core directly, which is a universally resolvable dependency.

These lines appear to be an artifact of the rolldown bundler (the file imports from ./_virtual/rolldown_runtime.mjs) rather than an intentional API design choice.

What version of Better Auth are you using?

1.4.18

System info

{
  "system": {
    "platform": "linux",
    "arch": "x64",
    "version": "#1 SMP PREEMPT_DYNAMIC Thu Jun  5 18:30:46 UTC 2025",
    "release": "6.6.87.2-microsoft-standard-WSL2",
    "cpuCount": 12,
    "cpuModel": "13th Gen Intel(R) Core(TM) i7-13700H",
    "totalMemory": "19.53 GB",
    "freeMemory": "15.83 GB"
  },
  "node": {
    "version": "v24.12.0",
    "env": "development"
  },
  "packageManager": {
    "name": "bun",
    "version": "1.3.9"
  },
  "frameworks": [
    {
      "name": "react",
      "version": "^19.2.4"
    }
  ],
  "databases": null,
  "betterAuth": {
    "version": "^1.4.18",
    "config": null

}

Which area(s) are affected?

Types

Additional context

  • This is related to the systemic type portability issues tracked in #5666
  • Both tsc and tsgo produce the same broken declarations — this is not a TypeScript compiler bug
  • The workaround is to add better-auth as a direct dependency of every consuming package, but this forces an unnecessary transitive dependency on packages that only need Zod types to resolve correctly
  • The export * from "zod" lines also pollute auto-import suggestions in IDEs for all consumers, since every Zod type appears as an import from better-auth:
    Image
Originally created by @aurelientanguy on GitHub (Feb 14, 2026). Originally assigned to: @himself65 on GitHub. ## Is this suited for github? - [x] Yes, this is suited for github ## To Reproduce 1. Set up a TypeScript monorepo with declaration emit (`emitDeclarationOnly: true`) 2. Create a package (e.g. `packages/auth`) that depends on `better-auth` and exports an `Auth` type derived from `betterAuth()` 3. Create a second package (e.g. `packages/api`) that imports the `Auth` type and also uses Zod schemas (directly or via `drizzle-zod`) 4. Create a consuming app (e.g. `apps/app`) that depends on `packages/api` but does **not** directly depend on `better-auth` 5. Run `tsc --emitDeclarationOnly` on `packages/api` 6. Observe the emitted `.d.ts` files — `ZodObject` generic parameters resolve as `import("better-auth").$strip` instead of `import("zod/v4/core").$strip` 7. When `apps/app` type-checks against these declarations, `import("better-auth")` is unresolvable (since `better-auth` is not a direct or hoisted dependency), causing types to collapse to `any` ## Current vs. Expected behavior ### Current `better-auth@1.4.18`'s `dist/index.d.mts` (lines 27, 29–30) contains wildcard re-exports of the entire Zod namespace: ```typescript export * from "zod"; export * from "zod/v4/core"; export * from "zod/v4"; ``` This makes **every** Zod type accessible via `import("better-auth")` — including internal types like `$strip`, `$ZodTypeInternals`, etc. When TypeScript's declaration emitter encounters Zod types (like the `$strip` second generic parameter of `ZodObject`), it picks the "shortest accessible module path." Since `better-auth` re-exports `zod/v4/core`, TypeScript resolves `$strip` as `import("better-auth").$strip` instead of `import("zod/v4/core").$strip`. Downstream consumers that don't have `better-auth` as a direct dependency then fail type-checking — the unresolvable `import("better-auth").$strip` causes types to collapse to `any`: ``` error TS7006: Parameter 'feature' implicitly has an 'any' type. ``` ### Expected `better-auth` should **not** re-export `zod`, `zod/v4`, and `zod/v4/core` from its public API surface. These wildcard re-exports leak internal implementation details into TypeScript's module resolution graph for all downstream consumers. Removing lines 27, 29–30 from `dist/index.d.mts` would fix the issue — TypeScript would then resolve `$strip` through `zod/v4/core` directly, which is a universally resolvable dependency. These lines appear to be an artifact of the rolldown bundler (the file imports from `./_virtual/rolldown_runtime.mjs`) rather than an intentional API design choice. ## What version of Better Auth are you using? 1.4.18 ## System info ```json { "system": { "platform": "linux", "arch": "x64", "version": "#1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025", "release": "6.6.87.2-microsoft-standard-WSL2", "cpuCount": 12, "cpuModel": "13th Gen Intel(R) Core(TM) i7-13700H", "totalMemory": "19.53 GB", "freeMemory": "15.83 GB" }, "node": { "version": "v24.12.0", "env": "development" }, "packageManager": { "name": "bun", "version": "1.3.9" }, "frameworks": [ { "name": "react", "version": "^19.2.4" } ], "databases": null, "betterAuth": { "version": "^1.4.18", "config": null } ``` ## Which area(s) are affected? Types ## Additional context - This is related to the systemic type portability issues tracked in #5666 - Both `tsc` and `tsgo` produce the same broken declarations — this is not a TypeScript compiler bug - The workaround is to add `better-auth` as a direct dependency of every consuming package, but this forces an unnecessary transitive dependency on packages that only need Zod types to resolve correctly - The `export * from "zod"` lines also pollute auto-import suggestions in IDEs for all consumers, since every Zod type appears as an import from `better-auth`: <img width="1215" height="638" alt="Image" src="https://github.com/user-attachments/assets/4400f6bd-27c4-4549-9b33-3d4f63dd1267" />
GiteaMirror added the bug label 2026-03-13 10:24:58 -05:00
Author
Owner

@himself65 commented on GitHub (Feb 16, 2026):

We won't fix this right now, as we need to re-export the zod type to fix the deceleration issue. But we will remove zod deps in the future

@himself65 commented on GitHub (Feb 16, 2026): We won't fix this right now, as we need to re-export the zod type to fix the deceleration issue. But we will remove zod deps in the future
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2872