-
Notifications
You must be signed in to change notification settings - Fork 6
Rest.ts vs RESTyped
RESTyped serves pretty much the same purpose as Rest.ts, but with some minor differences. This document provides a factual comparison so you can chose which library best suits your use case.
RESTyped is weightless. This means it works solely on types, and doesn't leave any trace after the TypeScript compiler is done processing the source code. Rest.ts on the other hand has a thin runtime layer.
There are pros and cons to each design, and most of the differences cited in the rest of this article stem from this one design criterion.
note: Although the core module of RESTyped is weightless, derived modules, like restyped-express-async may add a small amount of runtime code.
Rest.ts lifts the application code by abstracting away the details of individual endpoints. In practice, this difference is visible when you define and use your API:
Rest.ts
// In the definition:
createCat: POST `/cats/create`
// ...
// Then, at usage:
// You only worry about application logic, here "create a cat", not the network logic
// which says "make a POST request to /cats/create".
// You might want to encapsulate that call in a service of your own for large applications,
// but this abstraction is good enough that you can just use it as-is in medium-sized projects.
client.createCat(/* ... */);
RESTyped
// In the definition:
'/me/orders': {
POST: {
// ...
}
}
// Then, at usage:
// You still have to know the details of the underlying HTTP call.
// This might not be such a big deal if you encapsulate your API calls in a dedicated class
// (often called "a service" in frontend software), but you have to deal with this yourself.
// Repeating the string '/me/orders' in many places in your app is definitely not advisable.
client.post('/me/orders', /* ... */);
Both Rest.ts and RESTyped provide the core features you are looking for: Compile-time type-checking and IDE completion for your REST calls. The differences lie in how they provide these core features, and the extra stuff you can get for free.
While RESTyped provides good auto-completion support when you are using an already-defined API, it doesn't help you define the actual API. API definitions in RESTyped are free form interfaces, there is no safeguard preventing you from introducing a typo in the definition, and it isn't easy to discover the available keywords right from your editor.
Because you are using actual function calls in Rest.ts, you can simply start typing an HTTP verb followed by the endpoint path, and let intellisense guide you through the creation process of your API. The resulting code is also more compact with Rest.ts than with RESTyped.
Path parameters are awkward to deal with using RESTyped. The reason is that RESTyped uses the pathname for both identifying an endpoint, and making the actual call (see the "Abstraction" section above). Therefore, when using path parameters, type-inference doesn't work well, and you may have to explicitly provide the pathname in the type template in order to enable the type-checking features of RESTyped.
Another consequence of this, is in how endpoints are considered. Say you can query /cats/:id
with either PUT
, to update a cat, or DELETE
to remove said cat.
In Rest.ts these will be two distinct endpoints, say updateCat
and deleteCat
. In RESTyped, these will be one endpoint, which you can chose to call with PUT
or DELETE
.
Rest.ts, when used with a data validation library such as runtypes, provides out of the box runtime type checking.
If you are writing a client-server application in a vacuum, once and will never update it. Then there are practically no difference between Rest.ts and RESTyped with respect to input data. RESTyped might even perform better if your request data is complex to parse.
However, in most real-world scenarios, you will face malicious input, outdated clients, crawlers, and many unplanned usages of your API. TypeScript can only protect your application against programming errors inside the same application. Unlike in Java, if a user sends null
where you expected a string
, then Node.js, or any JavaScript runtime for that matter, will happily accept the input data. The bad data type will creep into the internals of your application and blow up at a random location, potentially far away from where it entered.
Ensuring consistency of the input data against the expected types shields your application from these kind of errors. Rest.ts with runtypes provides this out of the box. RESTyped lets you handle it yourself. And if you are not handling it at all you are doing it wrong.
Rest.ts is younger than RESTyped. I was looking for a library with the features of Rest.ts and stumbled upon RESTyped. While it did most of the job pretty well, it had slightly different design goals than those I had in mind, and I found it interesting to provide this alternative approach to the same problem.