Skip to content

Commit 63196d3

Browse files
Add typescript definition pillarjs#110
1 parent b5ad46b commit 63196d3

File tree

2 files changed

+211
-0
lines changed

2 files changed

+211
-0
lines changed

index.d.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
2+
import { OutgoingMessage } from "http";
3+
4+
export default Router;
5+
6+
type HttpMethods =
7+
'get' |
8+
'post' |
9+
'put' |
10+
'head' |
11+
'delete' |
12+
'options' |
13+
'trace' |
14+
'copy' |
15+
'lock' |
16+
'mkcol' |
17+
'move' |
18+
'purge' |
19+
'propfind' |
20+
'proppatch' |
21+
'unlock' |
22+
'report' |
23+
'mkactivity' |
24+
'checkout' |
25+
'merge' |
26+
'm-search' |
27+
'notify' |
28+
'subscribe' |
29+
'unsubscribe' |
30+
'patch' |
31+
'search' |
32+
'connect'
33+
34+
export interface RouterOptions {
35+
strict?: boolean;
36+
caseSensitive?: boolean;
37+
mergeParams?: boolean;
38+
}
39+
40+
export interface IncomingRequest {
41+
url?: string;
42+
method?: string;
43+
originalUrl?: string;
44+
params?: Record<string, string>;
45+
}
46+
47+
interface BaseRoutedRequest extends IncomingRequest {
48+
baseUrl: string;
49+
next?: NextFunction;
50+
route?: IRoute;
51+
}
52+
53+
export type RoutedRequest = BaseRoutedRequest & {
54+
[key: string]: any;
55+
}
56+
57+
export interface NextFunction {
58+
(err?: any): void;
59+
}
60+
61+
type IRoute = Record<HttpMethods, IRouterHandler<IRoute>> & {
62+
path: string;
63+
all: IRouterHandler<IRoute>;
64+
}
65+
66+
type RequestParamHandler = (
67+
req: IncomingRequest,
68+
res: OutgoingMessage,
69+
next: NextFunction,
70+
value: string,
71+
name: string
72+
) => void;
73+
74+
export interface RouteHandler {
75+
(req: RoutedRequest, res: OutgoingMessage, next: NextFunction): void;
76+
}
77+
78+
export interface RequestHandler {
79+
(req: IncomingRequest, res: OutgoingMessage, next: NextFunction): void;
80+
}
81+
82+
type ErrorRequestHandler = (
83+
err: any,
84+
req: IncomingRequest,
85+
res: OutgoingMessage,
86+
next: NextFunction
87+
) => void;
88+
89+
type PathParams = string | RegExp | Array<string | RegExp>;
90+
91+
type RequestHandlerParams =
92+
| RouteHandler
93+
| ErrorRequestHandler
94+
| Array<RouteHandler | ErrorRequestHandler>;
95+
96+
interface IRouterMatcher<T> {
97+
(path: PathParams, ...handlers: RouteHandler[]): T;
98+
(path: PathParams, ...handlers: RequestHandlerParams[]): T;
99+
}
100+
101+
interface IRouterHandler<T> {
102+
(...handlers: RouteHandler[]): T;
103+
(...handlers: RequestHandlerParams[]): T;
104+
}
105+
106+
type IRouter = Record<HttpMethods, IRouterMatcher<IRouter>> & {
107+
param(name: string, handler: RequestParamHandler): IRouter;
108+
param(
109+
callback: (name: string, matcher: RegExp) => RequestParamHandler
110+
): IRouter;
111+
all: IRouterMatcher<IRouter>;
112+
use: IRouterHandler<IRouter> & IRouterMatcher<IRouter>;
113+
handle: RequestHandler;
114+
route(prefix: PathParams): IRoute;
115+
}
116+
117+
interface RouterConstructor {
118+
new (options?: RouterOptions): IRouter & RequestHandler;
119+
(options?: RouterOptions): IRouter & RequestHandler;
120+
}
121+
122+
declare var Router: RouterConstructor;

test/types.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { createServer, OutgoingMessage } from 'http';
2+
import Router, {
3+
RouterOptions,
4+
RouteHandler,
5+
NextFunction,
6+
RoutedRequest,
7+
IncomingRequest
8+
} from '..';
9+
10+
const options: RouterOptions = {
11+
strict: false,
12+
caseSensitive: false,
13+
mergeParams: false
14+
};
15+
16+
// new constructor
17+
new Router().all('/', (req, res, next) => {})
18+
// direct call
19+
Router().all('/', (req, res, next) => {})
20+
21+
const router = new Router(options);
22+
const routerHandler: RouteHandler = (req, res, next) => {
23+
res.setHeader('Content-Type', 'plain/text');
24+
res.write('Hello')
25+
res.end('world')
26+
};
27+
28+
// test verb methods
29+
router.get('/', routerHandler);
30+
router.post('/', routerHandler);
31+
router.delete('/', routerHandler);
32+
router.patch('/', routerHandler);
33+
router.options('/', routerHandler);
34+
router.head('/', routerHandler);
35+
router.bind('/', routerHandler);
36+
router.connect('/', routerHandler);
37+
router.trace('/', routerHandler);
38+
router['m-search']('/', routerHandler);
39+
40+
41+
// param
42+
router.param('user_id', (req, res, next, id) => {
43+
type TReq = Expect<Equal<typeof req, IncomingRequest>>
44+
type TRes = Expect<Equal<typeof res, OutgoingMessage>>
45+
type TNext = Expect<Equal<typeof next, NextFunction>>
46+
type P1 = Expect<Equal<typeof id, string>>
47+
});
48+
49+
// middleware
50+
router.use((req, res, next) => {
51+
type TReq = Expect<Equal<typeof req, RoutedRequest>>
52+
type TRes = Expect<Equal<typeof res, OutgoingMessage>>
53+
type TNext = Expect<Equal<typeof next, NextFunction>>
54+
next();
55+
});
56+
57+
// RoutedRequest is extended with properties without type errors
58+
router.use((req, res, next) => {
59+
req.extendable = 'extendable'
60+
next();
61+
});
62+
63+
router.route('/')
64+
.all((req, res, next) => {
65+
type TReq = Expect<Equal<typeof req, RoutedRequest>>
66+
type TRes = Expect<Equal<typeof res, OutgoingMessage>>
67+
type TNext = Expect<Equal<typeof next, NextFunction>>
68+
next();
69+
})
70+
.get((req, res, next) => {
71+
type TReq = Expect<Equal<typeof req, RoutedRequest>>
72+
type TRes = Expect<Equal<typeof res, OutgoingMessage>>
73+
type TNext = Expect<Equal<typeof next, NextFunction>>
74+
});
75+
76+
77+
// valid for router from createServer
78+
createServer(function(req, res) {
79+
router(req, res, (err) => {})
80+
router.handle(req, res, (err) => {})
81+
})
82+
83+
84+
// Type test helper methods
85+
type Compute<T> = T extends (...args: any[]) => any ? T : { [K in keyof T]: Compute<T[K]> }
86+
87+
type Equal<X, Y> = (<T>() => T extends Compute<X> ? 1 : 2) extends <T>() => T extends Compute<Y> ? 1 : 2 ? true : false
88+
89+
type Expect<T extends true> = T extends true ? true : never

0 commit comments

Comments
 (0)