如何用TypeScript扩展Next.js默认类型 避免as强制类型转换
正确扩展Next.js useRouter类型的实现方案
错误原因
你之前的写法直接覆写了next/router模块的全量导出声明,没有保留原模块的其他类型定义,同时引用typeof router.useRouter形成了循环类型引用,因此会导致整个模块的类型完全失效。
推荐实现方案
方案1:直接增强NextRouter内置接口(最稳妥)
不需要修改自动生成的next-env.d.ts,单独新建自定义类型声明文件即可,比如types/next-router.d.ts,内容如下:
import 'next/router'; declare module 'next/router' { interface NextRouter { query: { // 你确认存在的固定query参数声明在这里 ticketNumber: string; // 保留默认query的泛用类型,兼容其他动态参数 } & Record<string, string | string[] | undefined>; } }
然后需要在tsconfig.json的include数组中加入该声明文件的匹配规则,示例:
{ "include": ["next-env.d.ts", "types/**/*.d.ts", "**/*.ts", "**/*.tsx"] }
配置完成后所有地方调用useRouter()返回的对象都会自动带上你定义的query类型,不需要额外加as强制转换。
方案2:重写useRouter函数返回类型
如果仅需要修改useRouter的返回值、不修改全局NextRouter类型,可以用以下写法:
import type { NextRouter } from 'next/router'; declare module 'next/router' { export function useRouter(): NextRouter & { query: { ticketNumber: string; } & Record<string, string | string[] | undefined>; } }
注意事项
- 不要修改Next自动生成的
next-env.d.ts文件,该文件会在项目依赖更新时被自动覆写,自定义类型单独放到独立的声明文件目录中更稳妥 - 如果
ticketNumber不是所有路由都存在的参数,可以在类型声明后加?设为可选,避免不存在该参数时报类型错误 - 末尾的
Record类型不可省略,否则访问其他未显式声明的query参数时会触发类型不存在的报错
内容的提问来源于stack exchange,提问作者Norfeldt
相关产品推荐
相关产品推荐

