cloudflare / cloudflare/vinext

Support the typedRoutes config option (statically typed links)

Open
#3,075 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.