Created
November 24, 2020 02:16
-
-
Save kazuma1989/795f2d6eda9213a655bc4dede2674de9 to your computer and use it in GitHub Desktop.
補完の効くSPA内遷移先一覧を定義する方法
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const paths = [ | |
'/settings/:id/:tab', | |
'/profile/:tab(foo)', | |
'/profile/', | |
'/users/:userId', | |
'/', | |
] as const; | |
/** | |
* SPA 内遷移のパス一覧 | |
* | |
* `Path[目的のパス]` で、"目的のパス" を返す関数が取得できる。 | |
* その関数を引数なしで呼べばキーの値がそのまま返るので、react-router の Route path に渡す値として使える。 | |
* 引数ありで呼べばパスパラメーター部分を置換した値が返るので、react-router の Link to として使える。 | |
* | |
* @example | |
* Path['/users/:userId']() === '/users/:userId'; | |
* Path['/users/:userId']({ userId: 'xxx' }) === '/users/xxx'; | |
* Path['/settings/:id/:tab']({ id: 'xxx', tab: 'yyy' }) === '/settings/xxx/yyy'; | |
* Path['/profile/:tab(foo)']({ 'tab(foo)': 'foo' }) === '/profile/foo'; | |
*/ | |
export const Path: { | |
[P in typeof paths[number]]: (param?: ParamObject<P>) => string; | |
} = Object.fromEntries( | |
paths.map(path => [ | |
path, | |
(param?: ParamObject<typeof path>) => | |
param | |
? path.replace( | |
/:([^/]+)/g, | |
(match, key: ParamNames<typeof path>) => | |
param[key]?.toString() ?? match, | |
) | |
: path, | |
]), | |
) as any; | |
// https://twitter.com/Quramy/status/1300758740317081601?s=20 | |
type ParamFromTemplate<T extends string> = T extends `:${infer P}` ? P : never; | |
type ParamNames<S extends string> = string extends S | |
? string | |
: S extends `${infer T}/${infer U}` | |
? ParamFromTemplate<T> | ParamNames<U> | |
: ParamFromTemplate<S>; | |
type ParamObject<T extends string> = { | |
[P in ParamNames<T>]?: string | number; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment