cloudflare / cloudflare/vinext
Support the typedRoutes config option (statically typed links)
- Dominant language
- TypeScript
- Stars
- 8.8k
- Forks
- 406
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 122
Description
## Summary
Support the stable `typedRoutes` config option (statically typed links). vinext's typegen already generates `.next/types/routes.d.ts` with route unions and a `ParamMap`, which is most of the machinery — what's missing is the typed-links file Next.js emits when `typedRoutes: true` is set, plus wiring for the config flag. `vinext check` currently reports `experimental.typedRoutes` as unsupported, and the stable top-level `typedRoutes` key isn't in the config support map at all.
## Motivation / problem
Apps that enable `typedRoutes` rely on `import type { Route } from 'next'` and compile-time validation of `href` values (e.g. lint/CI guards that keep internal links pointing at real routes). Migrating such an app to vinext silently loses the feature: the vendored `Route` type stays the `string & {}` fallback stub, so everything type-checks whether or not the route exists. For codebases that use typed routes as a correctness gate rather than a convenience, this is a migration blocker.
## Expected behaviour
With `typedRoutes: true` in `next.config.*`:
- Dev, build, and `vinext typegen` additionally emit the typed-links declaration file (Next 16 writes `.next/types/link.d.ts`): the `__next_route_internal_types__` namespace with `StaticRoutes` / `DynamicRoutes` / `RouteImpl`, plus `declare module` augmentations for `next` (real `Route`), `next/link` (typed `href`), `next/navigation` (typed `useRouter`, `redirect`, `permanentRedirect`), and `next/form`.
- The generated `next-env.d.ts` references the new file alongside `routes.d.ts`.
- `vinext check` reports `typedRoutes` as supported, with `experimental.typedRoutes` treated as a deprecated alias (matching Next, which stabilised the option).
## Actual behaviour
- The `typedRoutes` flag is not read anywhere; only `routes.d.ts` is generated.
- `Route` resolves to the vendored stub `string & {}`, so no href validation occurs.
- `check.ts` lists `experimental.typedRoutes` as `unsupported — typed routes not implemented`; the stable key is absent from `CONFIG_SUPPORT`.
## Reproduction context
Any Next.js 16 App Router project with `typedRoutes: true` in `next.config.ts`. Run `vinext typegen` (or dev/build) and observe that no typed-links declarations are generated and invalid `` values type-check. Observed against vinext main as of 2026-08-25 while scanning a six-app Next 16 monorepo for migration feasibility.
## Additional context
Implementation sketch, from reading both codebases:
- Next 16's reference implementation is compact: `route-types-utils.js` writes `link.d.ts` from `generateLinkTypesFile(manifest)` when `config.typedRoutes === true`. The template ports nearly verbatim, and `typegen.ts`'s existing route model (`patternToNextFormat`) already produces Next-format patterns for the `StaticRoutes` / `DynamicRoutes` unions.
- The vendored type tree (`packages/types/next/upstream/dist/`) already contains the modules the generated augmentations import from (`dist/client/link.d.ts`, `dist/client/components/redirect-error.d.ts`), so the emitted file should type-check without adapting the template's import paths.
- Config plumbing: pass `nextConfig.typedRoutes` through the `writeRouteTypes()` call sites in `index.ts` and the `typegen` CLI path; `warnDeprecatedConfigOptions` is the existing hook for the `experimental.typedRoutes` alias.
- Suggested scope for a first pass: App Router routes only (vinext's typegen currently models only the app dir). Next also folds Pages Router routes and redirect/rewrite sources into the generated unions — those, plus `experimental.strictRouteTypes`, could be deferred to follow-ups if that helps keep the first PR reviewable.
- Tests would extend `tests/typegen.test.ts`'s existing temp-project harness: static / dynamic / catch-all / route-group cases with the flag on, and a flag-off case asserting no typed-links file is emitted.
Contributor guide
Research direction
Start with the writeRouteTypes() call sites in index.ts and the typegen CLI path, then inspect check.ts, warnDeprecatedConfigOptions, and tests/typegen.test.ts. Done means typedRoutes and its experimental alias are handled, link.d.ts and next-env.d.ts are generated as described, and the existing temp-project harness covers flag-on route cases plus flag-off absence.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- build-system, developer-experience, testing
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100