Skip to content

Latest commit

 

History

History
106 lines (77 loc) · 2.78 KB

Typescript-Features.md

File metadata and controls

106 lines (77 loc) · 2.78 KB

Ketting has a number of features making it possible to add stricter typing to resources. It does this with generics.

By default, when you obtain a resource with follow(), you will get an object with type Resource<any>.

// authorRes is Resource<any>
const authorRes = await someRes.follow('item');

This causes the signatures of put() and get() to rougly look like this:

class Resource {
  get(): Promise<any>;
  put(body: any): Promise<void>
}

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 authorRes = await someRes.follow<Author>('item');

// Will have type Author
const author = await author.get();

The get and put signatures now look like this:

class Resource {
  get(): Promise<Author>;
  put(body: Author): Promise<void>
}

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');

When a Resource is typed, 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 possible to override the type for patch.

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>

tl;dr

These are the most relevant methods from the Resource type:

class Resource<TResource = any, TPatch = Partial<TResource>> {

  get(): Promise<TResource>;
  put(body: TResource): Promise<void> {
  delete(): Promise<void>; 

  post<TPostResource = any>(body: TPostResource): Promise<Resource<TPostResource>|null>;
  patch(body: TPatch): Promise<void>; 

  refresh(): Promise<TResource>;

  follow<TFollowedResource = any>(rel: string, variables?: LinkVariables): Follower<TFollowedResource>; 
  followAll<TFollowedResource = any>(rel: string): Promise<Array<Resource<TFollowedResource>>>;

  go<TGoResource = any>(uri: string): Resource<TGoResource>; 

}