Skip to content

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

@aurelientanguy

Description

@aurelientanguy

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 Systemic type issues across better-* packages ("cannot be named without a reference") (proposed parent issue) #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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinglockedLocked conversations after being closed for 7 days

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions