All Projects → aeirola → io-ts-promise

aeirola / io-ts-promise

Licence: MIT license
io-ts for developers who like Promises

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to io-ts-promise

best-queue
Queue in runtime based promise
Stars: ✭ 26 (-62.32%)
Mutual labels:  promise
conquerant
lightweight async/await for Clojure
Stars: ✭ 31 (-55.07%)
Mutual labels:  promise
microteam
小团队管理 是一款开源的微信小程序,主要用于日常的团队管理
Stars: ✭ 40 (-42.03%)
Mutual labels:  promise
sequence-as-promise
Executes array of functions as sequence and returns promise
Stars: ✭ 23 (-66.67%)
Mutual labels:  promise
Promise.allSettled
ES Proposal spec-compliant shim for Promise.allSettled
Stars: ✭ 93 (+34.78%)
Mutual labels:  promise
emacs-promise
Promises/A+ for Emacs
Stars: ✭ 56 (-18.84%)
Mutual labels:  promise
relaks
Asynchrounous React component
Stars: ✭ 49 (-28.99%)
Mutual labels:  promise
of
🍬 Promise wrapper with sugar 🍬
Stars: ✭ 13 (-81.16%)
Mutual labels:  promise
iworker
Promise-based wrapper for worker_threads
Stars: ✭ 18 (-73.91%)
Mutual labels:  promise
ADM-treeView
Pure AngularJs TreeView
Stars: ✭ 30 (-56.52%)
Mutual labels:  promise
lightflow
A tiny Promise-inspired control flow library for browser and Node.js.
Stars: ✭ 29 (-57.97%)
Mutual labels:  promise
hangman-game
A responsive hangman game built with vanilla javascript, html, and css. Animated with GSAP and canvas animations.
Stars: ✭ 22 (-68.12%)
Mutual labels:  promise
make-cancellable-promise
Make any Promise cancellable.
Stars: ✭ 17 (-75.36%)
Mutual labels:  promise
p-cache
Decorator to memoize the results of async functions via lru-cache.
Stars: ✭ 21 (-69.57%)
Mutual labels:  promise
ProtoPromise
Robust and efficient library for management of asynchronous operations in C#/.Net.
Stars: ✭ 20 (-71.01%)
Mutual labels:  promise
eslint-config-welly
😎 ⚙️ ESLint configuration for React projects that I do. Feel free to use this!
Stars: ✭ 21 (-69.57%)
Mutual labels:  promise
parcel-plugin-goodie-bag
provides the Promise and fetch goodies needed for IE(11) support w/ parcel bundle loading
Stars: ✭ 15 (-78.26%)
Mutual labels:  promise
react-nested-loader
The easiest way to manage loaders/errors inside a button. NOT an UI lib.
Stars: ✭ 62 (-10.14%)
Mutual labels:  promise
wxapp-socket
用于微信小程序socket通信的封装
Stars: ✭ 17 (-75.36%)
Mutual labels:  promise
postmessagejs
postmessage-promise is a client-server like, WebSocket like, full Promise syntax (postMessage.then etc.) supported postMessage library. 一个类 client-server 模式、类 WebSocket 模式、全 Promise 语法支持的 postMessage 库
Stars: ✭ 33 (-52.17%)
Mutual labels:  promise

io-ts-promise

While io-ts is a great library, it can be a bit alienating unless you are familiar with functional programming. So if you just want to ensure the runtime types for the data fetched from your API, you might be looking for something simpler. This is where io-ts-promise tries to help out.

It provides the following:

Usage

Promise chain decoding

Decode data from Promise based APIs, without having to worry about how to retrieve data from the Either values returned by the io-ts types.

import * as t from 'io-ts';
import * as tPromise from 'io-ts-promise';

const Person = t.type({
  name: t.string,
  age: t.number,
});

fetch('http://example.com/api/person')
  .then(response => tPromise.decode(Person, response.json()))
  .then(typeSafeData =>
    console.log(`${typeSafeData.name} is ${typeSafeData.age} years old`),
  );

tPromise.decode also supports currying, so we can simplify the code with

fetch('http://example.com/api/person')
  .then(response => response.json())
  .then(tPromise.decode(Person))
  .then(typeSafeData =>
    console.log(`${typeSafeData.name} is ${typeSafeData.age} years old`),
  );

As with any Promise-based API, you can also use tPromise.decode in async code as following

const response = await fetch('http://example.com/api/person');
const typeSafeData = await tPromise.decode(Person, response.json());
console.log(`${typeSafeData.name} is ${typeSafeData.age} years old`);

Identifying errors

When building long promise chains, you might handle errors somewhere else than directly next to the function producing the error. In these cases you might want to identify the errors in order to act accordingly. Errors produced by the decode function due to incompatible data can be identified by either using the type guard tPromise.isDecodeError(error), or checking the error type with error instanceof tPromise.DecodeError. For example:

fetch('http://example.com/api/not-a-person')
  .then(response => response.json())
  .then(tPromise.decode(Person))
  .then(typeSafeData =>
    console.log(`${typeSafeData.name} is ${typeSafeData.age} years old`),
  )
  .catch(error => {
    if (tPromise.isDecodeError(error)) {
      console.error('Request failed due to invalid data.');
    } else {
      console.error('Request failed due to network issues.');
    }
  });

Creating custom types

Writing custom io-ts types is a bit cryptic, so this library provides a simpler way of extending existing io-ts types, or creating your own from scratch. All you need is a function which decodes incoming values, and another which encodes it back.

import * as t from 'io-ts';
import * as tPromise from 'io-ts-promise';

// New type extending from existing type
const Price = tPromise.extendType(
  t.number,
  // Decode function takes in number and produces wanted type
  (value: number) => ({
    currency: 'EUR',
    amount: value,
  }),
  // Encode function does the reverse
  price => price.amount,
);

// And use them as part of other types
const Product = t.type({
  name: t.string,
  price: Price,
});

fetch('http://example.com/api/product')
  .then(response => response.json())
  .then(tPromise.decode(Product))
  .then(typeSafeData =>
    console.log(
      `${typeSafeData.name} costs ${typeSafeData.price.amount} ${
        typeSafeData.price.currency
      }`,
    ),
  );

Alternatively, you can define the type from scratch, in which case the decoder will receive a value of unknown type to decode into desired runtime type.

// Custom type from scratch
const Price = tPromise.createType(
  // Decode function takes in unknown and produces wanted type
  (value: unknown) => {
    if (typeof value === 'number') {
      return {
        currency: 'EUR',
        amount: value,
      };
    } else {
      throw new Error('Input is not a number');
    }
  },
  // Encode function does the reverse
  price => price.amount,
);

Decoders

In case you only need to read data into your application, you can use decoders which only convert data in one way.

Note: io-ts doesn't support decoders in its nested types such as t.array or t.type. So only use decoders for top level data structures. The decode function of this library suppports both types and decoders.

The easiest way is to create a decoder is to extend and existing io-ts type, and only perform the desired additional modification on top of that.

import * as tPromise from 'io-ts-promise';

const Person = t.type({
  name: t.string,
  age: t.number,
});

const ExplicitPerson = tPromise.extendDecoder(Person, person => ({
  firstName: person.name,
  ageInYears: person.age,
}));

fetch('http://example.com/api/person')
  .then(response => tPromise.decode(ExplicitPerson, response.json()))
  .then(typeSafeData =>
    console.log(
      `${typeSafeData.firstName} is ${typeSafeData.ageInYears} years old`,
    ),
  );

You can also create decoders from scratch using createDecoder, but I have yet to find a good example of where this would be convenient.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].