vscode 默认不提示 next.js app router 路径,因 ts server 无法识别 app/ 目录路由语义;需同时配置 tsconfig.json 的 "moduleresolution": "bundler" 和 next.config.js 的 experimental.typedroutes = true,并重启 ts server。

VSCode 默认不提示 Next.js 路由路径,不是插件没装对,而是 TypeScript Server 根本“看不见”app/目录的路由语义 —— 必须启用 experimental.typedRoutes 并配对 moduleResolution: "bundler",否则所有 href、useRouter().push() 里的字符串都只是普通字符串,没有类型约束也没有补全。
为什么 app/ 下的页面路径不补全
Next.js App Router 的路由不是靠文件系统路径直映射,而是靠约定生成(比如 app/posts/[id]/page.tsx → /posts/[id])。VSCode 自带的 JS/TS 语言服务只做静态文件扫描,不会运行 Next.js 的路由解析逻辑。它看到的只是一个普通 TSX 文件,而不是一个“可被路由访问的端点”。
常见现象包括:
-
<link href="/nonexistent">不报错,也无补全 -
router.push("/settings")中的"/settings"无法 Ctrl+Click 跳转到对应page.tsx - 输入
/后无路径列表弹出,甚至输错路径也不提示
必须配 tsconfig.json + next.config.js 才生效
仅装插件或改 VSCode 设置没用。补全能力依赖 TypeScript 编译器是否加载了 Next.js 提供的路由类型定义,而这由两个配置共同触发:
-
tsconfig.json中必须有:"moduleResolution": "bundler"(Next.js 13.4+ 强制要求) -
next.config.js中必须开启:experimental: { typedRoutes: true } - 项目根目录需存在
next-env.d.ts(Next.js CLI 会自动生成,若手动删过需重跑next dev) - 改完后执行
Developer: Restart TS Server(Cmd+Shift+P),不能只重启 VSCode
href 补全仍不准?检查写法是否绕过类型检查
即使启用了 typedRoutes,以下写法依然无法补全或校验:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
-
href={"/user/" + id}:动态拼接 → 类型丢失 → 补全失效 -
href={`/posts/${slug}`}:同上,TS 无法推导slug是否匹配app/posts/[slug]/page.tsx -
href="/dashboard/settings/"(末尾斜杠):Next.js 实际路由是/dashboard/settings,多出的/会导致类型不匹配,补全可能跳过该路径
更可靠的做法是:
- 用字面量加
as const:const href = "/dashboard/settings" as const - 在
app/目录下严格按约定命名文件,避免嵌套括号组名(如app/(auth)/login/page.tsx)—— 括号内容不参与路由,但可能干扰路径推导 - 多段动态路由(如
app/[lang]/[region]/page.tsx)只对静态前缀补全,/en/US/可能提示,/zh/CN/不会自动列出
调试时 router.push() 跳转没反应?先确认路由实例是否注入
这和提示无关,但常被误认为“补全失效导致跳转失败”。真实原因往往是:
-
app/router.ts或类似文件中createRouter()返回值未export default -
main.tsx中未调用root.render(...)前完成RouterProvider注入 - 使用了
useRouter()但在服务端组件(无"use client")里调用 —— 此时 hook 无效,且控制台可能静默失败
验证方式:在客户端组件中打印 useRouter() 返回值,看是否有 push、refresh 等方法;若为 undefined,说明 Provider 没挂载成功。
最易忽略的一点:typedRoutes 生成的类型只覆盖 app/ 目录,pages/ 路由完全不受影响,也不需要这些配置 —— 如果你混用两种路由,别指望同一套提示逻辑同时生效。










