Skip to content

Instantly share code, notes, and snippets.

@aherve
Last active May 25, 2017 08:00
Show Gist options
  • Save aherve/088db76b1d67489253ab94d3c85a2ec3 to your computer and use it in GitHub Desktop.
Save aherve/088db76b1d67489253ab94d3c85a2ec3 to your computer and use it in GitHub Desktop.
// First we define a standard generic structure for an api response
interface ApiMethodResponse<T> {
statusCode?: number
data: T
}
// The `apiMethod` constructor will take an `ApiMethodDefinition` as argument.
type ApiMethodDefinition<T> = (req: Request) => Promise<ApiMethodResponse<T>>
// Now the constructor:
export function apiMethod<T> (f: ApiMethodDefinition<T>): RequestHandler {
// here we take benefit from Request & Response typings
return async function (req: Request, res: Response) {
// No way you forget the try/catch
try {
// call the apiMethod definition
const {statusCode, data} = await f(req)
if (data) {
// default the status to 200, and send data if any
res.status(statusCode || 200).send(data)
} else {
// default the status to 200 and send empty response
res.sendStatus(statusCode || 200)
}
} catch (e) {
// always catch any unexpected error
res.status(500).send(e)
}
}
}
@fox1t
Copy link

fox1t commented May 25, 2017

I found that you have to put a question mark also on data prop in the ApiMethodResponse interface, because you return also an object without generic T if db returns null if (!user) {return {statusCode: 404}}

interface ApiMethodResponse<T> {
  statusCode?: number
  data?: T
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment