ITADN

TS2883: inferred return types from withAuth() / refreshSession() are non-portable when consumer pins a different @workos-inc/node version

#422ClosedLeestex 创建于 2026-05-06
L
Leestexcommented
**Describe the bug** TypeScript emits `TS2883` (and on some configurations, the related `TS2742`) on consumer code that infers return types from `withAuth()` or `refreshSession()`: ``` error TS2883: The inferred type of 'requireAuth' cannot be named without a reference to 'User' from '@workos-inc/authkit-nextjs/node_modules/@workos-inc/node'. This is likely not portable. A type annotation is necessary. ``` The error reproduces whenever the consumer's resolved version of `@workos-inc/node` differs from the version that satisfies authkit-nextjs's transitive `^9.0.0` range. Package managers then install a duplicate nested copy under `node_modules/@workos-inc/authkit-nextjs/node_modules/@workos-inc/node/`, and TypeScript can no longer write a portable declaration for any inferred type that surfaces `User` (or `OauthTokens`, `AuthenticationResponse`) through the public API. **To Reproduce** 1. In a Next.js project, install `@workos-inc/authkit-nextjs@^4.0.1` and pin `@workos-inc/node` directly to a version that doesn't match `^9.0.0`'s currently-resolved point version, e.g. `9.2.0` while authkit-nextjs's transitive resolution is still at `9.1.1`. With Yarn 4 + node-modules linker this is what `dependabot[bot]` produces every time it bumps the direct pin. 2. Write any function whose return type is inferred from `withAuth()`. A minimal repro: ```ts // lib/auth/session.ts import { withAuth, getSignInUrl } from "@workos-inc/authkit-nextjs" import { redirect } from "next/navigation" export async function requireAuth() { const session = await withAuth() if (!session.user) { const signInUrl = await getSignInUrl() redirect(signInUrl) } return session as typeof session & { user: NonNullable<typeof session.user> } } ``` 3. Run `tsc --noEmit` (or in any monorepo package with `declaration: true` / `composite: true` / `isolatedDeclarations`). 4. Observe `TS2883` on the `requireAuth` declaration. Confirmed in `yarn.lock` that there are two resolved versions of `@workos-inc/node`: ``` "@workos-inc/node@npm:9.2.0": # consumer direct dep "@workos-inc/node@npm:^9.0.0": # transitive from authkit-nextjs → 9.1.1 ``` `yarn dedupe --check '@workos-inc/node'` reports the split: ``` @workos-inc/node@npm:^9.0.0 can be deduped from @workos-inc/node@npm:9.1.1 to @workos-inc/node@npm:9.2.0 ``` **Expected behavior** `tsc` should emit a portable declaration. authkit-nextjs's public types should resolve to a single canonical copy of `@workos-inc/node`'s types regardless of the consumer's resolved version, so that any inferred type referencing `User` / `UserInfo` / `Session` / `HandleAuthSuccessData` is namable from a stable path. **Root cause** `@workos-inc/node` is declared in `dependencies` (https://github.com/workos/authkit-nextjs/blob/main/package.json#L41), but its types are surfaced into authkit-nextjs's public-API interfaces in `src/interfaces.ts`: ```ts import type { AuthenticationResponse, OauthTokens, User } from '@workos-inc/node'; export interface Session { user: User; ... } export interface UserInfo { user: User; ... } export interface HandleAuthSuccessData extends Session { oauthTokens?: OauthTokens; authenticationMethod?: AuthenticationResponse['authenticationMethod']; ... } ``` A regular `dependencies` entry on a SDK whose types appear in the public API allows the package manager to install a separate nested copy whenever the consumer's resolved version diverges. The same hazard exists with `next` and `react` — and authkit-nextjs already declares both as `peerDependencies` for exactly this reason. **Proposed fix** Move `@workos-inc/node` from `dependencies` to `peerDependencies`. The peer-dep contract forces a single resolved copy in the consumer tree by construction. PR coming. This is a breaking change, but in practice the impact is small: every authkit-nextjs consumer already has to call `@workos-inc/node` directly for the parts of the WorkOS SDK that authkit doesn't wrap (organization management, user management, FGA, audit logs, etc.). **Workaround (for anyone hitting this today)** `yarn dedupe '@workos-inc/node'` in the consumer's repo collapses the duplicate, and either a `resolutions` pin or a CI-side `yarn dedupe --check '@workos-inc/node'` step (run after install) prevents the regression from recurring on future Dependabot bumps. **Environment** - `authkit-nextjs` version: 4.0.1 (also affects all 4.x; same class of bug applied to earlier majors with their own `@workos-inc/node` ranges) - `@workos-inc/node` versions involved: 9.1.1 (transitive) vs 9.2.0 (consumer direct) - Next.js version: any - TypeScript version: 6.0.x (also reproduces on 5.x with the same diagnostic code) - Package manager: Yarn 4.14.1 with `nodeLinker: node-modules` (the same hazard exists on npm/pnpm whenever versions split) - OS: macOS / Linux (build-time only — not runtime, not browser-dependent) **Additional context** Same root cause manifested as `TS2742` on earlier versions before TS6 changed the diagnostic. Closed issue [#181](https://github.com/workos/authkit-nextjs/issues/181) (1.x era) was a related-but-different surfacing of the public-types-export problem.
关闭于 2026-06-25 0 条评论