Skip to content

Instantly share code, notes, and snippets.

@danielberndt
Last active December 31, 2017 14:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielberndt/2e1d8fffad0bda537dea964d54682182 to your computer and use it in GitHub Desktop.
Save danielberndt/2e1d8fffad0bda537dea964d54682182 to your computer and use it in GitHub Desktop.
This is the result of some prototyping with zeit/micro and creating type-safe handlers that progressively enhance the `req` variable via function composition
import * as http from "http";
interface Handler<T extends http.IncomingMessage> {
(req: T, res: http.ServerResponse): any;
}
type WithDB = {db: number};
function withPg<T extends http.IncomingMessage>(handler: Handler<T & WithDB>): Handler<T> {
return (req, res) => {
const newReq = req as T & WithDB;
newReq.db = 5;
return handler(newReq, res);
};
}
type WithUser = {user: string};
function withUser<T extends http.IncomingMessage & WithDB>(
handler: Handler<T & WithUser>
): Handler<T> {
return (req, res) => {
const newReq = req as T & WithUser;
newReq.user = "Daniel " + req.db;
return handler(newReq, res);
};
}
function withLogger<T extends http.IncomingMessage>(
handler: Handler<T & {log: (a: any) => void}>
): Handler<T> {
return (req, res) => {
const newReq = req as T & {log: (a: any) => void};
newReq.log = a => console.log("[logger]", a);
return handler(newReq, res);
};
}
// note ts' type inference does not enforce "withUser" to be within "withPg" :(
const withLogHandler: Handler<http.IncomingMessage> = withPg(
withUser(
withLogger((req, res) => {
req.log("bla");
console.log("req.db", req.db);
return {ok: true};
})
)
);
export default withLogHandler;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment