restyped-express-async icon indicating copy to clipboard operation
restyped-express-async copied to clipboard

Export the type of what is returned by AsyncRouter

Open henrikra opened this issue 6 years ago • 1 comments

I have situation like this:

// fileA.ts
const router = RestypedRouter<MyAPI>(app);
configureRouter(router);

// fileB.ts
function configureRouter(router: any) { // <-- What type here
  // do stuff with router
}

As you can see from the code I am passing RestypedRouter as parameter to a function because I am doing stuff with it inside the function. But the problem is that I can't get the type for the router.

When I look generated index.d.ts file inside node_modules/restyped-express-async I will see definition like this image

import * as express from 'express-serve-static-core';
import { RestypedBase, RestypedRoute } from 'restyped';
export interface TypedRequest<T extends RestypedRoute> extends express.Request {
    body: T['body'];
    params: T['params'];
    query: T['query'];
}
export default function AsyncRouter<APIDef extends RestypedBase>(app: express.Express | express.Router): {
    route: <Path extends keyof APIDef, Method extends "GET" | "POST" | "PUT" | "PATCH" | "HEAD" | "DELETE" | "OPTIONS">(path: Path, method: Method, handler: (req: TypedRequest<APIDef[Path][Method]>, res: express.Response) => Promise<APIDef[Path][Method]["response"]>) => void;
    use: any;
    get: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["GET"]>, res: express.Response) => Promise<APIDef[Path]["GET"]["response"]>) => void;
    post: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["POST"]>, res: express.Response) => Promise<APIDef[Path]["POST"]["response"]>) => void;
    put: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["PUT"]>, res: express.Response) => Promise<APIDef[Path]["PUT"]["response"]>) => void;
    delete: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["DELETE"]>, res: express.Response) => Promise<APIDef[Path]["DELETE"]["response"]>) => void;
    patch: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["PATCH"]>, res: express.Response) => Promise<APIDef[Path]["PATCH"]["response"]>) => void;
    options: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["OPTIONS"]>, res: express.Response) => Promise<APIDef[Path]["OPTIONS"]["response"]>) => void;
    head: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["HEAD"]>, res: express.Response) => Promise<APIDef[Path]["HEAD"]["response"]>) => void;
};

As you can see the return type of AsyncRouter is NOT exported.

🍏 Solution Export return type as type. Add something like this to the types

export interface InternalRouter<APIDef extends RestypedBase> {
  route: <Path extends keyof APIDef, Method extends "GET" | "POST" | "PUT" | "PATCH" | "HEAD" | "DELETE" | "OPTIONS">(path: Path, method: Method, handler: (req: TypedRequest<APIDef[Path][Method]>, res: express.Response) => Promise<APIDef[Path][Method]["response"]>) => void;
  use: any;
  get: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["GET"]>, res: express.Response) => Promise<APIDef[Path]["GET"]["response"]>) => void;
  post: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["POST"]>, res: express.Response) => Promise<APIDef[Path]["POST"]["response"]>) => void;
  put: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["PUT"]>, res: express.Response) => Promise<APIDef[Path]["PUT"]["response"]>) => void;
  delete: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["DELETE"]>, res: express.Response) => Promise<APIDef[Path]["DELETE"]["response"]>) => void;
  patch: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["PATCH"]>, res: express.Response) => Promise<APIDef[Path]["PATCH"]["response"]>) => void;
  options: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["OPTIONS"]>, res: express.Response) => Promise<APIDef[Path]["OPTIONS"]["response"]>) => void;
  head: <Path extends keyof APIDef>(path: Path, handler: (req: TypedRequest<APIDef[Path]["HEAD"]>, res: express.Response) => Promise<APIDef[Path]["HEAD"]["response"]>) => void;
}

⚠️ Workaround: My current workaround is just to copy paste the code above to my own source code. But this is not maintainable because if the type changes in Restyped library I have change my local source code too which is not idea.

👑 Please tell me if you have any questions and tell me if this is clear for you 👍

henrikra avatar Aug 06 '18 08:08 henrikra

Hey, I know it's been two years but if you're still interested in this, I forked this package to ianmartorell/restyped-express and I also want to use the function type in my code, but I'm not sure what's the best way to go about adding it. Any help would be appreciated.

ianmartorell avatar Nov 14 '20 12:11 ianmartorell