fp-ts/typescript steer clear of chaining multiple pipes

Is there a more concise way to handle nested pipes in fp-ts when working with TypeScript? Perhaps using some form of syntactic sugar like Do notation? I'm trying to avoid this kind of nested pipe structure:


pipe(
  userId,
  O.fold(
    () => setUser('No user found'),
    (uId: string) => {
      fetchUser(uId).then((response: Either<NonEmptyArray<string>, User>) => {
        pipe(
          response,
          E.fold(
            () => setUser('Unable to fetch user'),
            (user: User) => setUser(JSON.stringify(user, null, 2))
          )
        );
      });
    }
  )
);

Answer №1

Optimizing performance involves delaying the execution of fold to minimize unnecessary nesting.

The beauty of algebraic effects is that they can be combined seamlessly without having to determine whether a value exists or an operation has failed.

Consider a scenario where a TaskEither instance, manipulated using chain, retains the initial error if no user is found. Otherwise, it holds either the error returned by fetchUser or the data of the User in case of success.

See working example here

import { pipeable as P, option as O, taskEither as TE, nonEmptyArray as NA } from "fp-ts";

type User = { name: string };

// Global state (side effect)
let user: string | undefined = undefined;
const setUser = (usr: string) => (user = usr);

// Input provided
const userId: O.Option<string> = O.some("Arun");

const fetchUser: (uid: string) => TE.TaskEither<NA.NonEmptyArray<string>, User> = uid =>
  TE.taskEither.of({ name: "Arun" });
  // An error case would be: TE.left(NA.of("Unable to fetch user"))

const res = P.pipe(
  userId,
  TE.fromOption(() => NA.of("No user found")),
  TE.chain(fetchUser),
  TE.map(user => JSON.stringify(user, null, 2)),
  TE.fold( // Performing fold only at the end before applying the effect
    err => TE.taskEither.fromIO(() => { setUser(err[0]); }),
    user => TE.taskEither.fromIO(() => { setUser(JSON.stringify(user, null, 2)); })
  ),
  TE.chain(() => TE.taskEither.fromIO(() => { console.log(user); }))
);

// Execute the effect
res();

PS: It's assumed here that your fetchUser represents an asynchronous operation generating a TaskEither. You can switch it back to Either if necessary.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for setting up a proxy with an enum

I am facing an issue with setting up a Proxy for an enum. Specifically, I have an enum where I want to assign a value to this.status using a Proxy. However, despite my expectations, the output "I have been set" does not appear in the console. Can anyone ex ...

What is the best method for storing a third-party image in cache?

Running my website, I aim to achieve top-notch performance scores using LightHouse. I have successfully cached all the images I created (Cache-Control: public, max-age=31536000). Unfortunately, third-party website images are not cached. How can I cache t ...

Invoking a Typescript function from the Highcharts load event

Struggling to call the TypeScript function openDialog() from the events.load of Highcharts? Despite using arrow functions, you are running into issues. Take a look at the code snippet below: events: { load: () => { var chart : any = this; ...

Angular's FormGroup for reactive forms is a powerful feature that allows for

Why am I unable to type in the input field before setting a value? html <form action="" [formGroup]="titleForm"> <input class="note-title" type="text" formControlName="title"> </form> ...

Typescript has a knack for uncovering non-existent errors

When I attempted to perform a save operation in MongoDB using Mongoose, the code I initially tried was not functioning as expected. Upon conducting a search online, I came across a solution that worked successfully; however, TypeScript continued to flag an ...

The mat-table fails to populate with data retrieved from the rest service

I have successfully fetched an array from my REST service and displayed some information from the response on the page. However, I am facing issues populating my mat-table and I'm unsure of the cause. The mat-table was functioning properly in the past ...

Struggling to properly test the functionality of my NgForm call in Angular2+

I've been trying to test the login functionality by inputting username and password in an NgForm, but I keep encountering unsuccessful attempts. Is there a vital step that I may be overlooking? Currently, I'm facing this error message: Chrome 6 ...

Tips for retrieving modified data from a smart table in Angular 4

Currently, I am working on an angular project where I am utilizing smart table. Here is a snippet of my .html file: <ng2-smart-table [settings]="settings" [source]="source" (editConfirm)="onSaveConfirm($event)" (deleteConfirm)="onDeleteConfirm($event ...

You are unable to apply 'use client' on a layout element in Next.js

While attempting to retrieve the current page from the layout.txt file, I encountered errors after adding 'use client' at the top of the page: Uncaught SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data parseMod ...

Update the input value with the selected option from the dropdown menu in Angular

How can I dynamically set the value of an input field based on the selection from a dropdown menu in Angular using Reactive Forms? Below is my HTML code: <nb-card> <nb-card-header> Services </nb-card-header> <nb-card-body&g ...

Enhancing React Flow to provide updated selection and hover functionality

After diving into react flow, I found it to be quite user-friendly. However, I've hit a roadblock while attempting to update the styles of a selected node. My current workaround involves using useState to modify the style object for a specific Id. Is ...

Showing container element only if certain condition is met but display the children in Angular 2+

I am looking to create a grid-style view for a list of Angular components, where I can display up to 4 components in each row. The question that comes close to what I need is the following: Angular 2 NgIf, dont render container element on condition but sh ...

strictBindCallApply causing issues when working with generic parameters

Take a look at this slightly contrived code snippet: export function evaluate<T>(this: { value: T }) { return this.value; } class SomeClass { value: ''; constructor() { const result = evaluate.call(this); } } You might notice ...

What is the procedure for linking the value (<p>John</p>) to the mat form field input so that it displays as "John"?

Can I apply innerHTML to the value received from the backend and connect it to the matInput? Is this a viable option? ...

Issue encountered while executing ./node_modules/.bin/cucumber-js within GitLab CI

I've encountered an issue while setting up a continuous integration build for my node project. Despite the fact that npm run test runs smoothly in my local setup, I am facing an exception in GitLab CI. The error arises from the following test command ...

Tips for incorporating flow and TypeScript typings into an NPM module

Are there any resources available for adding both flow and typescript typings to an NPM module at the same time? I've been struggling to find a comprehensive guide on this topic, and it seems to be a common issue faced by open source library maintain ...

Angular: Clicking on a component triggers the reinitialization of all instances of that particular component

Imagine a page filled with project cards, each equipped with a favorite button. Clicking the button will mark the project as a favorite and change the icon accordingly. The issue arises when clicking on the favorite button causes all project cards to rese ...

What is the best method for incorporating an Angular Component within a CSS grid layout?

I recently started learning Angular and am currently working on a project that requires the use of a CSS grid layout. However, I'm facing an issue with inserting a component inside a grid area specified by grid-area. My attempt to achieve this in app ...

The parameter 'X' cannot be assigned to the argument of type 'X'

Hello there! I'm diving into Type Script for the first time with VSCode. Encountering these errors: error TS2322: Type '() => string' is not assignable to type 'string'. error TS2322: Type '() => number' is ...

What is the best way to access the input element of ng-content from the parent component?

Creating a unique component in the following structure <div class="custom-search-field" [ngClass]="{'expanding': expanding}"> <ng-content></ng-content> </div> When using this component, users are expected to include ...