Last active
July 8, 2021 14:22
-
-
Save dac09/73fe5c04571f55095a9ef446bb6263e9 to your computer and use it in GitHub Desktop.
ParamParsing
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
type ParamType<constraint> = constraint extends 'Int' ? number : constraint extends 'Boolean' ? boolean : constraint extends 'Float' ? number : string | |
type RouteParams<Route> = Route extends `${string}/${infer Rest}` | |
? A.Compute<ParsedParams<Rest>> | |
: {} | |
type QueryParams = Record<string | number, string | number | boolean> | |
type ParsedParams<PartialRoute> = | |
// {a:Int}/[...moar] | |
PartialRoute extends `{${infer Param}:${infer Constraint}}/${infer Rest}` | |
? // check for greedy match e.g. {b}/{c:Int} | |
// Param = b}/{c, Rest2 = {c, Constrait = Int so we reconstruct the old one {c + : + Int + } | |
Param extends `${infer Param2}}/${infer Rest2}` | |
? { [ParamName in Param2]: string } & | |
ParsedParams<`${Rest2}:${Constraint}}`> & | |
ParsedParams<`${Rest}`> | |
: { [Entry in Param]: ParamType<Constraint> } & ParsedParams<`${Rest}`> | |
: // has type, but at the end e.g.{d:Int} | |
PartialRoute extends `{${infer Param}:${infer Constraint}}` | |
? // Greedy match order 2 | |
Param extends `${infer Param2}}/${infer Rest2}` | |
? { [ParamName in Param2]: string } & | |
ParsedParams<`${Rest2}:${Constraint}}`> | |
: { [Entry in Param]: ParamType<Constraint> } | |
: // no type, but has stuff ater it {c}/{d} | |
PartialRoute extends `{${infer Param}}/${infer Rest}` | |
? { [ParamName in Param]: string } & ParsedParams<`${Rest}`> | |
: // last one with no type e.g. {d} | |
PartialRoute extends `{${infer Param}}` | |
? { [ParamName in Param]: string } | |
: // if theres a non param | |
PartialRoute extends `${string}/${infer Rest}` | |
? ParsedParams<`${Rest}`> | |
: {} | |
/// ====== TEST CASES ========= | |
type mixed = RouteParams<'/path/{b:Int}/{c}/{d}'> | |
type oneEach = RouteParams<'/path/{b:Int}/{c}/{d:Boolean}'> | |
type oneEachDiffOrder = RouteParams<'/path/{b}/{c:Int}/{d:Boolean}'> | |
type noTypesatall3 = RouteParams<'/path/{b}/{c}/{d}'> | |
type aftersOnly2 = RouteParams<'/path/{b}/{c}'> | |
type aftersOnly4 = RouteParams<'/path/{b}/{c}/{d}/{e}'> | |
type aftWithTypes = RouteParams<'/path/{b:Int}/{c}'> | |
type aftWithTypes2 = RouteParams<'/path/{b:Int}/{c:Boolean}'> | |
// greedy matching {b}/{c:Int} | |
type aftWithTypes3 = RouteParams<'/path/{b}/{c:Int}/{d:Boolean}'> | |
// greedy matching reversed {b:Int}/{c} | |
type aftWithTypes4 = RouteParams<'/path/{b:Int}/{c}/{d:Boolean}'> | |
type aftMIxed = RouteParams<'/path/{b:Int}/{c:Boolean}/{d}/{e:Int}'> | |
type aftMIxed2 = RouteParams<'/path/{b:Int}/{c:Boolean}/{d}/{e:String}/{f}'> | |
type nonParamsInTheMiddle = | |
RouteParams<'/user/{userId}/edit/likes/{likeId:Int}'> | |
type badParams = | |
RouteParams<'/mega/{bId:Int}/s/d/{year:Int}/{month:Int}/{monthDates}/e/{eId:Int}/s'> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment