如何定義這樣一個 TypeScript 泛型,遍歷路由配置樹並累積路徑
我有
type Route = {
path: string
children?: readonly Route[]
}
const root = {
path: "a",
children: [
{ path: "b" },
{ path: "c", children: [{ path: "d", children: [{ path: "e" }] }] }
],
} as const satisfies Route;
我想定義一個 TypeScript 泛型 Convert,使得 Convert<typeof root> 的輸出為字串列舉 'a' | 'a/b' | 'a/c' | 'a/c/d' | 'a/c/d/e'
type Convert<T extends Route> = ?我試了類似的東西
type Convert<T extends Route, Prefix extends string = ''> =
`${Prefix}/${T['path']}` | (
T["children"] extends readonly Route[]
? {
[K in number]: Convert<T['children'][K], `${Prefix}/${T['path']}`>;
}[number]
: never)
但是 Output="/a" | "/a/b" | "/a/c" 不夠深入。
https://www.typescriptlang.org/play?#code/C4TwDgpgBASg9gV2NAvFA3gWAFBSmAQ2AAsAuKAZ2ACcBLAOwHMc8BjY2gGwBNqJ6A-OT4FucepxCxEyANoBdHAF8cOVuKpRqcOMChosufETJQARATMAaFlHZde-crNt50xkuTMAjM1CU2Rm4epmas1nYcPHz0zu6EnubcEfbRTlCy8SZeEH5K8v4FKkbygUpQBBR2GnoURLQUAGa0EFXwSBAA3KrYoJBQAKIAHpCsemgA5AQTUAA+UFMA9N4z80vei6yrCwTLm4vc2+v73IsQEz190ADC4gBuENTAADwAKlAQQ8j03G0yEFYoAAFPjNIYfL78X6UGgMRj6BYTAB8CJwAAMACToEEQMFKRZY16yCYJYgTeRKNFzKAAClcUCJYSijnoZgKn2+0JEYgkUnackUQTwUAEGHpwoyAGkoAwoPQEABbbyPeTkW70B5PN7E1Is8mySWlKCY7Gg2hDfGE4mk8mUpHdIV4JSyeVKlXiqDkegQTUASku4Ggw0IP2eAA0UWgwxDOVUEPQANb0OAAd3oIqg0a9PseDquUAA8kgwEgEcGCKH1ZqXlc4I0tDpgEikUA
感謝你的幫助!
答案#1
毫無疑問,有許多方式可以做到這一點。這裡有一個方法:
type Convert<T extends Route> =
T['path'] | (
T extends { children: readonly (infer R extends Route)[] } ?
`${T['path']}/${Convert<R>}` : never
);
我在那裡所做的只是輸出 path 屬性,並遞歸抓取 R,也就是 children 屬性中的 Route 聯集,然後應用 Convert<R>… 並將其附加到 path 屬性後面,並加上一個斜線。
讓我們確保它能正常運作:
type Expect = 'a' | 'a/b' | 'a/b/c' | 'a/b/c/d' | 'a/b/c/d/e'
type Actual = Convert<typeof root>;
// type Actual = "a" | "a/b" | "a/c" | "a/c/d" | "a/c/d/e"
看起來不錯。
程式碼的 Playground 連結
