Last active
May 21, 2023 12:32
-
-
Save faustienf/481f17e5cf0a544ee0f9bc0d0cfbaf87 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// Unility types begin | |
type Split< | |
S extends string, | |
Delimiter extends string | |
> = S extends `${infer Head}${Delimiter}${infer Tail}` | |
? [Head, ...Split<Tail, Delimiter>] | |
: S extends Delimiter | |
? [] | |
: [S]; | |
type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {}; | |
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ( | |
k: infer I | |
) => void | |
? I | |
: never; | |
// Unility types end | |
// Path types begin | |
type ExtraxtPathParam<P extends string> = Extract< | |
Split<P, "/">[number], | |
`:${string}` | |
>; | |
type ExtractParamEnum<E extends string> = Split<E, "|">[number]; | |
type ExtraxtParamName<P extends string> = P extends `${infer RP}?` | |
? ExtraxtParamName<RP> extends { [name in infer N]: infer V } | |
? { [name in Extract<N, string>]?: V } | |
: never | |
: P extends `:${infer N}(${infer E})` | |
? { [name in N]: ExtractParamEnum<E> } | |
: P extends `:${infer N}` | |
? { [name in N]: string } | |
: never; | |
type ExtractParams<Path extends string> = Simplify< | |
UnionToIntersection<ExtraxtParamName<ExtraxtPathParam<Path>>> | |
>; | |
// Path types end | |
// TEST | |
type Expect<T extends true> = T; | |
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y | |
? 1 | |
: 2 | |
? true | |
: false; | |
// --- // | |
type Params = | |
ExtractParams<"/url/:filter(popular|latest)/:userId/:tag(daily|weekly|monthly)?/:search?">; | |
type tests = [ | |
Expect<Equal<ExtractParams<"/url/search">, {}>>, | |
Expect< | |
Equal< | |
ExtractParams<"/url/:search?">, | |
{ | |
search?: string; | |
} | |
> | |
>, | |
Expect< | |
Equal< | |
ExtractParams<"/url/:search">, | |
{ | |
search: string; | |
} | |
> | |
>, | |
Expect< | |
Equal< | |
ExtractParams<"/url/:filter(popular|latest)">, | |
{ | |
filter: "popular" | "latest"; | |
} | |
> | |
>, | |
Expect< | |
Equal< | |
ExtractParams<"/url/:filter(popular|latest)?">, | |
{ | |
filter?: "popular" | "latest"; | |
} | |
> | |
>, | |
Expect< | |
Equal< | |
ExtractParams<"/url/:filter(popular|latest)/:userId/:tag(daily|weekly|monthly)?/:search?">, | |
{ | |
filter: "popular" | "latest"; | |
userId: string; | |
tag?: "daily" | "weekly" | "monthly"; | |
search?: string; | |
} | |
> | |
> | |
]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
typescriptlang.org/play