我正在将一些代码移至TS,并且一直在努力为一组路由功能定义一种类型。它们就是这样的:
const root: Route = () => 'root'
root.child = () => `${root()}/child`
root.child.grandchild = () => `${root.child()}/grandchild`
我试图在嵌套属性的索引签名旁边定义某种递归可调用类型或接口,但没有成功:
type Route = {
(): string
[key: string]: Route
}
关于我该怎么做的任何想法或想法?
答案 0 :(得分:3)
根据您要尝试执行的操作,有几种选择。
如果您使用常规的function
定义,则可以在声明该函数的范围内向该函数添加其他属性,TS会将这些属性识别为该函数的属性:
function root() { return 'root' }
function child() { return `${root()}/child` }
child.grandchild = () => `${root.child()}/grandchild`
root.child = child;
root.child.grandchild() //ok
另一种选择是使用Object.assign
一次性创建具有属性的函数:
const root = Object.assign(() => 'root', {
child: Object.assign(() => `${root()}/child`, {
grandchild: () => `${root.child()}/grandchild`
})
});
root.child.grandchild()
这两个选项实际上都不使用您的Router
接口,该接口允许以后添加任何字符串属性。为此,我认为最简单的选择是创建一个将在内部使用Object.assign
但也将使用所需类型的辅助函数:
type Route = {
(): string
[key: string]: Route
}
function createRoute(fn: () => string, other: Record<string, Route> = {}) {
return Object.assign(fn, other);
}
const root: Route = createRoute(() => 'root', {
child: createRoute(() => `${root()}/child`, {
grandchild: createRoute(() => `${root.child()}/grandchild`)
})
})