named-urls
named-urls copied to clipboard
Typescript support
Hi, Is there any plan or option to give types for the methods? I'm using the package, and working on routes' structure enforcement.
Hi, I use this declaration:
declare module 'named-urls' {
interface Routes { [path: string]: string | Routes };
interface ReverseParams { [path: string]: number | string };
function include(base: string, routes: Routes): Routes;
function reverse(pattern: string, params?: ReverseParams): string;
function reverseForce(pattern: string, params?: ReverseParams): string;
}
I'm very shaky on Typescript, but I think the above include
declaration can be improved with generics:
function include<B, R>(base: B, routes: R): { toString(): B } & { [K in keyof R]: string | any }
That at least lets the Typescript follow 1 level deeper and autocomplete the first levels of include()
calls.
const routes = {
dog: include('/dog', {
cat: include('cat', { mouse: 'mouse' }),
})
}
// Typescript will follow/autocomplete the following:
// routes.dog (toString() or cat)
// routes.dog.cat (string)
The string | any
at the 2nd level is obviously wrong, because instead of any
you would want to recurse the type (like the function is recursing). This might just take someone with faaaar more Typescript skills than me to come in and bop how you follow the recursing logic, but thought I'd add my contribution!
Hey @max-barry (or anyone visiting this thread), feel free to send a PR with TS declarations 👍
For anyone interested - I believe here's the typing for include
. I'd make a PR, but the best way to make this typed would be to rewrite everything with TS, and I'm not sure I have enough free time on my hands
function include<Routes>(base: string, routes: Routes): { [P in keyof Routes]: Routes[P] } & { toString(): string };
The typing for include
can further be simplified to:
interface Include {
<Routes>(path: string, routes: Routes): Routes & { toString(): string };
}
Together with the typings provided by @azixMcAze , we get the following declaration:
declare module "named-urls" {
export interface Include {
<Routes>(path: string, routes: Routes): Routes & { toString(): string };
}
export interface Reverse {
(pattern: string, params?: ReverseParams): string;
}
export interface ReverseParams {
[path: string]: number | string;
}
export interface Routes {
[path: string]: string | Routes;
}
export type ReverseForce = Reverse;
export const include: Include;
export const reverse: Reverse;
export const reverseForce: ReverseForce;
}
@kennedykori Looks great! Feel free to send a PR so we can include these types with the package
Oh nice, might spare some time to work on it. Are you okay with converting the project into a typescript project or would you rather I publish the decoration file to DefinitelyTyped? Making this a ts project might require that any future contributors to the project be at-least familiar with typescript. But it will also make it easier to evolve the library and the declarations as they will be on the same repository. @tricoder42 what would be your preference?
Definitely just convert it to Typescript. Typescript is my default choice nowadays 👍
Awesome, will work on it.