-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
dist/index.d.mts re-exports entire zod namespace, causing import("better-auth").$strip in downstream declaration emit #7975
Description
Is this suited for github?
- Yes, this is suited for github
To Reproduce
- Set up a TypeScript monorepo with declaration emit (
emitDeclarationOnly: true) - Create a package (e.g.
packages/auth) that depends onbetter-authand exports anAuthtype derived frombetterAuth() - Create a second package (e.g.
packages/api) that imports theAuthtype and also uses Zod schemas (directly or viadrizzle-zod) - Create a consuming app (e.g.
apps/app) that depends onpackages/apibut does not directly depend onbetter-auth - Run
tsc --emitDeclarationOnlyonpackages/api - Observe the emitted
.d.tsfiles —ZodObjectgeneric parameters resolve asimport("better-auth").$stripinstead ofimport("zod/v4/core").$strip - When
apps/apptype-checks against these declarations,import("better-auth")is unresolvable (sincebetter-authis not a direct or hoisted dependency), causing types to collapse toany
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
tscandtsgoproduce the same broken declarations — this is not a TypeScript compiler bug - The workaround is to add
better-authas 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 frombetter-auth:
