TS2883: inferred return types from withAuth() / refreshSession() are non-portable when consumer pins a different @workos-inc/node version
**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 条评论