Better typing with Ketting
Ketting is a generic hypermedia client that supports HAL, HTML, JSON-API, and HTTP Links (and soon also Siren).
Version 5 is currently in development, and one of the major new features is much deeper support for Typescript typing.
Here’s how it works.
Normally to get to a resource, you start with a bookmark and follow links
(by rel
), and perform some http method on them:
import Ketting from 'ketting';
const bookmark = 'https://api.example.org/home';
const ketting = new Ketting(bookmark);
const authorResource = await ketting
.follow('article')
.follow('item')
.follow('author');
const authorBody = await authorResource.get();
console.log(authorBody);
In this example, the Typescript type for authorResource
is Resource<any>
,
and authorBody
is any
.
If you know what the shape of the object is that you’re receiving via GET
,
you can specify this on the relevant follow()
function:
type Author = {
firstName: string,
lastName: string,
};
// Will have type Resource<Author>
const authorResource = await ketting
.follow('article')
.follow('item')
.follow<Author>('author');
// Will have type Author
const author = await author.get();
This same feature also exists on other functions that return resources.
// Returns Resource<Author>[]
const resources = await resource.followAll<Author>('item');
// Returns Resource<Author>
const resource = await recource.go<Author>('?relative-link');
Furthermore, once a resource is typed, it has a few more effects. It also
causes the put()
request to require the same type:
// Throws error due to missing 'lastName'.
authorResource.put({
firstName: 'Foo',
});
It also assumes that the type for the patch()
method is Partial<Author>
,
meaning that the assumption is that the HTTP Patch method takes a a JSON
object that’s a subset of ‘Author’.
Not every API will take that approach with Patch, so it’s also always possible to override the type for patch.
type Author = {
// ...
};
type SomeFancyPatchFormat = {
// ...
};
const res:Resource<Author, SomeFancyPatchFormat> = await otherRes.follow('...');
Lastly, if your API creates new resources with POST
, and the server returns
201 Created
and a Location
header, the post()
function returns a resource
of the same type.
const authorCollection = await res.follow('author-collection');
const newAuthor:Author = {
firstName: 'Ursula',
lastName: 'Le Guin',
};
const newAuthorResource = await authorCollection.post(newAuthor);
// newAuthorResource will now be typed as Resource<Author>
This feature does not have stable release, but you can the alpha now:
npm i ketting@5.0.0.alpha.0
If you have any feedback, let us know via a Github Issue.