Skip to content

Instantly share code, notes, and snippets.

@Schniz
Last active August 8, 2019 06:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Schniz/299f17cfad933a7b91f97f6c1009b29c to your computer and use it in GitHub Desktop.
Save Schniz/299f17cfad933a7b91f97f6c1009b29c to your computer and use it in GitHub Desktop.
A record combinator for fp-ts TaskEither
import * as te from 'fp-ts/lib/TaskEither';
import * as arr from 'fp-ts/lib/Array';
import { pipe } from 'fp-ts/lib/pipeable';
type TaskEither<A, B> = te.TaskEither<A, B>;
type TERight<T> = T extends TaskEither<any, infer R> ? R : never;
/**
* Transforms an object of `TaskEither`s into a TaskEither of the resolved objects.
* Keeping keys and values type safe
*/
export function record<L, T extends { [key: string]: TaskEither<L, any> }>(
rec: T,
): TaskEither<L, { [key in keyof T]: TERight<(typeof rec)[key]> }> {
return pipe(
Object.entries(rec),
arr.map(([key, value]) =>
pipe(
value,
te.map<any, [keyof T, any]>(x => [key, x]),
),
),
arr.array.sequence(te.taskEither),
te.map(xs => {
const x: { [key in keyof T]: TERight<(typeof rec)[key]> } = {} as any;
for (const [key, val] of xs) {
x[key] = val;
}
return x;
}),
);
}
// fetchJSON<T>(url): TaskEither<Error, T>
function fetchUserWithPosts(
userId: string
): te.TaskEither<Error, { user: User, posts: Post[] }> {
return record({
user: fetchJSON<User>("/users/1"),
posts: fetchJSON<Post[]>("/users/1/posts")
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment