You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为嵌套路由函数定义TypeScript类型?

如何为嵌套路由函数定义TypeScript类型?

我太懂这种迁移时卡壳的感觉了——这种可以无限嵌套的路由函数类型,确实容易让TypeScript新手(甚至老手)挠头。先回顾下你的场景:

const root: Route = () => 'root'
root.child = () => `${root()}/child`
root.child.grandchild = () => `${root.child()}/grandchild`

你尝试的type Route = { (): string; [key: string]: Route }思路方向是对的,但问题出在TypeScript的严格校验上:直接把普通的() => string函数赋值给Route类型时,TS会认为这个函数不具备索引签名要求的嵌套属性,从而抛出错误。

解决思路

我们需要让TS认可:一个返回字符串的函数,同时可以被扩展出任意数量的同类型嵌套属性。这里有两种实用的实现方案:

方案1:交叉类型+工具函数包装

先定义正确的交叉类型,再通过工具函数把普通函数"升级"成Route类型,绕过直接赋值的类型校验:

// 定义Route类型:既是返回string的函数,又能拥有任意字符串键的Route子属性
type Route = (() => string) & Record<string, Route>;

// 工具函数:将普通函数断言为Route类型,告诉TS它后续会被扩展嵌套属性
function createRoute(fn: () => string): Route {
  return fn as Route;
}

// 现在使用完全符合类型要求
const root = createRoute(() => 'root');
root.child = createRoute(() => `${root()}/child`);
root.child.grandchild = createRoute(() => `${root.child()}/grandchild`);

// 测试调用,类型推断完全正常
console.log(root()); // "root"
console.log(root.child.grandchild()); // "root/child/grandchild"

方案2:接口定义(本质和方案1一致)

如果你更习惯用接口语法,也可以这样写:

interface Route {
  (): string;
  [key: string]: Route;
}

// 同样用工具函数辅助创建
function createRoute(fn: () => string): Route {
  return fn as Route;
}

// 使用方式和方案1完全相同
const root = createRoute(() => 'root');
root.child = createRoute(() => `${root()}/child`);

为什么之前的写法不行?

你之前的类型定义逻辑本身没错,但TypeScript对函数类型的赋值有严格校验:普通的() => string函数并不自动具备Route类型要求的索引签名属性。通过createRoute的类型断言,我们相当于给TS打了个"招呼":这个函数后续会被扩展嵌套属性,放心把它当作Route类型处理。

内容的提问来源于stack exchange,提问作者Guilherme Baron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:47:54