Utils functions to use with Task.
isInstanceOf(Constructor1, Constructor2, ...) => (instance: any) => instance is Constructor1 | Constructor2 | ...
It is an util function to use with caseError. isInstanceOf takes any number of constructors (or classes) and returns a function that tells us if an object is an instance of any of those constructors. In case it is, it is also typed as well (see type guards).
classDog{bark(){return'WOOF!';}}classCat{meow(){return'Meeeeeoooooooow';}}constisDog=isInstanceOf(Dog);// This example is only for demonstration porpuses.// I should actually prefer the animals to be polymorphic.consttalk=(animal: Dog|Cat)=>{if(isDog(animal)){// animal is typed as Doganimal.bark();}else{// animal is typed as Catanimal.meow();}}caseError(predicate, errHandler)
caseError takes a predicate (a function to a boolean) and an error handler. If predicate returns true when called with the rejected error, then errHandler is called with the error and it's return value is returned. Else, the rejected error is rejected again.
import{Task}from'@ts-task/task';import{caseError}from'@ts-task/utils';// rejectedTask is a Task<never, FooError | BarError>constrejectedTask=Task.reject(Math.random()>0.5 ?
newFooError() :
newBarError());rejectedTask.catch(err=>// err is FooError | BarErrorTask.reject(err)).catch(caseError(isInstanceOf(FooError),err=>// err is a FooErrorTask.resolve('foo '+err.toString()))).catch(err=>// err is a BarError (since the FooError case was resolved)Task.reject(err));Note: have in mind that TypeScript does duck typing checks, hence
FooErrorandBarErrorshould have different properties to let TypeScript infere they are different, since TypeScript has structural typing instead of nominal typing.
toPromise(task)
toPromisefunction naturally transforms a Task into a Promise.
import{Task}from'@ts-task/task';import{toPromise}from'@ts-task/utils';// resolvedTask is a Task<number, never>constresolvedTask=Task.resolve(9);// resolvedPromise is Promise<number>constresolvedPromise=toPromise(resolvedTask);// rejectedTask is a Task<never, Error>constrejectedTask=Task.resolve(newError());// rejectedPromise is Promise<never>, rejected with ErrorconstrejectedPromise=toPromise(rejectedTask);task.pipe(share())
As Tasks are lazy, the Task's code isn't executed until it's resolved. But, for the same reason the Task's code is executed each time it is forked (operators - including .map, .chain and .catchmethods - do fork the Task). sharefunction is an operator that resolves the Task to that point and returns a Taskresolved (or rejected) with that value, so original Task's code is executed only once.
import{Task}from'@ts-task/task';import{share}from'@ts-task/utils';consttask=newTask<string,never>(resolve=>{console.log('Task\'s code is called');resolve('Foo');});constsharedTask=task.pipe(share);sharedTask.fork(err=>console.log(err),val=>console.log(val));sharedTask.fork(err=>console.log(err),val=>console.log(val));sharedTask.fork(err=>console.log(err),val=>console.log(val));// The message "Task's code is called" will be logged only once (even when forking multiple times).Gonzalo Gluzman 💻📖 | Hernan Rajchert 💻🎨📖🤔 |
|---|
This project follows the all-contributors specification. Contributions of any kind are welcome!