Skip to content

Instantly share code, notes, and snippets.

@cameron-martin
Last active July 24, 2019 11:56
Show Gist options
  • Save cameron-martin/9f1c49c9ce08e33c42b3e5634cea6beb to your computer and use it in GitHub Desktop.
Save cameron-martin/9f1c49c9ce08e33c42b3e5634cea6beb to your computer and use it in GitHub Desktop.
A typesafe router sketch
interface RouteVariable<T> {
parse(value: string): { value: T, rest: string } | false;
}
const int: RouteVariable<number> = undefined as any;
const segment: RouteVariable<string> = undefined as any;
type RouteVariables<T> = { [K in keyof T]: RouteVariable<T[K]> };
type AddRoute<R> = <T extends any[]>(
literals: TemplateStringsArray,
...placeholders: RouteVariables<T>
) => (render: (...args: T) => R) => void;
class Router<R> {
public route!: AddRoute<R>;
constructor(configure: (route: AddRoute<R>) => void) {
configure(this.route);
}
resolve(path: string): R | null {
throw new Error("Not implemented");
}
}
// 1. Add routes
// At construction time
const router = new Router<React.ReactElement<any>>(route => {
route`/user/${int}`(id => <div>User {id}</div>);
route`/user/${segment}/comments/${int}`((userName, commentId) => <div />);
});
// After construction
router.route`/user/${segment}/comments/${int}/edit`(
(userName, commentId) => <div />,
);
// 2. Ask the router to resolve a path
router.resolve("/user/1"); // Returns <div User 1</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment