Skip to content

Instantly share code, notes, and snippets.

@faustienf
Last active May 21, 2023 12:32
Show Gist options
  • Save faustienf/481f17e5cf0a544ee0f9bc0d0cfbaf87 to your computer and use it in GitHub Desktop.
Save faustienf/481f17e5cf0a544ee0f9bc0d0cfbaf87 to your computer and use it in GitHub Desktop.
// 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;
}
>
>
];
@faustienf
Copy link
Author

faustienf commented May 21, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment