= A & string;
+type TypedRoute = Route>;
+
+type InferTypedRoute = T extends TypedRoute ? U : never;
+type UnknownOrObject = T extends object ? T : {};
+type InferredKeys = keyof UnknownOrObject>;
+type HasSaved = InferredKeys extends never ? never : R;
+type HasNoSaved = InferredKeys extends never ? R : never;
+
+type MergeRoute = TypedRoute<
+ Union.Merge> | UnknownOrObject>>
+>;
+type MergeRouteMap = Union.Strict<{
+ [K in keyof R]: R[K] extends TypedRoute ? MergeRoute :
+ R[K] extends RouteMap ? MergeRouteMap :
+ R[K]
+}>;
+
+interface RouteMap {
+ [key: string]: string | TypedRoute | RouteMap;
+}
+type InferRouteMap = Union.Strict<{
+ [K in keyof R]: R[K] extends RouteMap ? InferRouteMap :
+ R[K] extends TypedRoute ? InferTypedRoute :
+ never
+}>;
+
+function typedRoute = {}>(path: string): TypedRoute;
+function typedRoute(
+ path: string
+): TypedRoute & Partial>>>;
+function typedRoute(path: string): string {
+ return path;
+}
+
+function routeMap(
+ basePath: P, map: R
+): Union.Strict<{ index: P } & MergeRouteMap>;
+function routeMap(basePath: string, map: R): { index: string } & R;
+function routeMap(basePath: string, map: RouteMap): RouteMap {
+ return Object.keys(map).reduce((obj, key) => {
+ const route: RouteMap | string = map[key];
+ const newValue = typeof route === 'object'
+ ? routeMap(basePath, route)
+ : `${basePath}${map[key]}`;
+ return {
+ ...obj,
+ [key]: newValue,
+ };
+ }, { index: basePath } as RouteMap);
+}
+
+function reverseUrl(
+ route: HasSaved, params: InferTypedRoute
+): string
+function reverseUrl(
+ route: HasNoSaved, params?: Record
+): string
+function reverseUrl(route: string, params?: object): string {
+ const reversed = compile(route);
+
+ return reversed(params);
+}
+
+export {
+ typedRoute,
+ routeMap,
+ reverseUrl,
+};
+
+export type {
+ TypedRoute,
+ InferTypedRoute,
+ InferRouteMap,
+ RouteMap,
+};
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..e1e8d2e
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,30 @@
+
+{
+ "compileOnSave": true,
+ "compilerOptions": {
+ "allowJs": false,
+ "allowSyntheticDefaultImports": true,
+ "baseUrl": "./",
+ "declaration": true,
+ "lib": [
+ "es2020",
+ "dom"
+ ],
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "outDir": "./build",
+ "rootDir": "./src",
+ "removeComments": false,
+ "sourceMap": false,
+ "skipLibCheck": true,
+ "strict": true,
+ "target": "es2015"
+ },
+ "include": [
+ "./src/**/*"
+ ],
+ "exclude": [
+ "node_modules",
+ "./src/**/*.test.ts"
+ ]
+}
\ No newline at end of file