A lot of apps use Typescript / JavaScript + Flow for frontend and backend code but I haven’t seen apps take advantage of this to create rest APIs that are statically typed end to end. I decided to set up what was needed to get a fully typed API on top of express. It’s worked pretty well for some personal projects so I’m sharing it here.
For posterity, at the time of writing I’m using Typescript v3.0.1 and Express v4.16.3.
There are two main files in my backend setup. The first contains my API definition and looks something like this:
For each API route you can define the type of the body and query parameters and what the response should look like. My responses are typed as objects with a data and status property but you could also extend it to include whatever you want - for example, a header property.
Express also allows you to specify parameters in your routes. So /api/share/:id would match routes like /api/share/123456 where 123456 would be made available via the id property on the Express request object. When the route is /api/share/:id, the params property for the route should be {id: string}. Ideally there should be something complaining if the route and params property are inconsistent in the API definition but Typescript doesn’t parse strings when type checking so it’s something that we’ll have to live with.
This API definition is used by the second main file, a custom router:
The results (shown with visual studio code), trying an invalid route:
Trying an incorrect status:
Trying incorrect data:
Trying a correct route:
A route that requires the user to be logged in makes the user available to the handler:
The frontend setup has 1 file that looks something like:
And the result when making an API request in frontend code: