Skip to content

Instantly share code, notes, and snippets.

@mykeels
Last active December 11, 2023 19:30
Show Gist options
  • Save mykeels/587e7933753e053cec5cbb783a8491e2 to your computer and use it in GitHub Desktop.
Save mykeels/587e7933753e053cec5cbb783a8491e2 to your computer and use it in GitHub Desktop.
/*
Path matching
-------
by Mykeels (@mykeels) #urls
See tests below
*/
/* _____________ Your Code Here _____________ */
type Paths = '/abc' | '/foo/:id' | '/bar' | (string & {});
declare function FooComponent<TPath extends Paths, TPathTemplate extends Paths.TemplateOf<TPath>>(
props: {
href: TPathTemplate extends Paths.Templates ? TPath : never
}
): any;
declare namespace Paths {
type Templates = Template<Paths>;
type Template<T extends string> =
T extends `${infer Prefix}:${infer Param}/${infer Rest}`
? `${Prefix}${string}/${Template<Rest>}`
: T extends `${infer Prefix}:${infer Rest}`
? `${Prefix}${string}`
: T;
type TemplateOf<
TPath extends string,
TPathTemplate extends Templates = Templates
> = TPathTemplate extends infer T extends string
? TPath extends T
? TPath extends `${T}/${string}`
? never
: T
: never
: never;
}
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type testCases = [
Expect<
Equal<Paths.TemplateOf<`/foo/hello`>, `/foo/${string}`>
>,
Expect<
Equal<Paths.TemplateOf<`/abc`>, `/abc`>
>,
Expect<
Equal<
Paths.TemplateOf<`/foo/abc/bar`>,
never
>
>,
];
const urls = [
FooComponent({
href: '/bar'
}),
FooComponent({
href: '/foo/hello'
}),
FooComponent({
// @ts-expect-error
href: '/foo/hello/wrong-url'
}),
FooComponent({
href: '/abc'
}),
FooComponent({
// @ts-expect-error
href: '/wrong-url'
}),
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment