我声明了一个从url中提取参数的类型:
type ExtractParams<Path extends string> =
Path extends `${infer Start}/:${infer Param}/${infer Rest}`
? ExtractParams<Start> & ExtractParams<Rest> & { [Key in Param]: string; }
: Path extends `${infer Start}/:${infer Param}`
? ExtractParams<Start> & { [Key in Param]: string }
: {}
代码运行良好:
type X1 = ExtractParams<'/courses/:courseId/classes/:classId'>
// ^? { classId: string; } & { courseId: string; }
这里是Playground Link
但这里有两件事可以改进:
1.避免重复
如果你检查ExtractParams
类型定义,你可以看到我使用了嵌套条件。外部条件查找/:
和/
之间的参数。内部条件查找字符串末尾的参数。所以,我想把/${infer Rest}
声明为可选的,但是我不知道如何在模板文字类型中声明一些可选的东西。你能帮我解释一下吗?
2.合并交点
现在输出看起来很难看,因为每个参数都有自己的对象。有没有办法合并这些对象?
更新:
从以下答案中得到了合并交叉点的答案:https://stackoverflow.com/a/58965725/2284240
为了在我的代码中合并交叉点,我可以像这样更新它:
type Expand<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
type Params<Path extends string> = Expand<ExtractParams<Path>>;
type X1 = Params<'/courses/:courseId/classes/:classId'>
// ^? { classId: string; courseId: string }
更新Playground Link
不把它作为答案贴出来,因为,我还在寻找一个解决方案避免重复
1条答案
按热度按时间yvfmudvl1#
我推荐的方法是用
"/"
个字符将路径分割成一个路径段的并集:这是一个尾递归条件类型,并为您的示例生成如下内容:
然后你可以只使用那些以
:
字符开始的段作为你的输出类型的键。使用键重Map来禁止任何不以
:
开始的联合成员。对于生成看起来是你想要的
Playground链接到代码