typescript - Is there a way not to return error wrapped by TaskEither? - Stack Overflow

admin2025-04-18  2

I'm working with fp-ts library. My function runs in parallel 2 other functions (lets call them first and second) that can either fail or succeed. They both return something like TE.TaskEither<Error, User>

So my function calls them pretty straighforward

TE.sequenceArray([first, second])

This function return type is TE.TaskEither<Error, ReadonlyArray<User>>

Now, the behavior is supposed to be like this:

case errors, succeed:
of [err, err], _ -> left(user does not exist)
of _, [el] -> right(el)
of _, _ -> left(internal server error)

Meaning if any of users is found, the function should return ReadonlyArray<User>> with either 2 or 1 users, and not throw error.

If there are 2 errors thrown meaning no user is found it should also return Error wrapped in TaskEither.

Sorry if my explanation is a bit blurry I'm still pretty new to fp-ts so please be kind to me :)

I've tried to use TE.fold and TE.chain but the issue is that I can't find the way to ignore error when one of calls return it

I tried:

F.pipe(
  TE.sequenceArray([fist, second]),
  TE.chain(successes => {
     if (successes.length > 0) {
        return TE.right(successes);
    } else {
      return TE.left(Error());
    }
  }),
  TE.map(results => results.flat()),
);

This solution seems to ignore my if statement

I'm working with fp-ts library. My function runs in parallel 2 other functions (lets call them first and second) that can either fail or succeed. They both return something like TE.TaskEither<Error, User>

So my function calls them pretty straighforward

TE.sequenceArray([first, second])

This function return type is TE.TaskEither<Error, ReadonlyArray<User>>

Now, the behavior is supposed to be like this:

case errors, succeed:
of [err, err], _ -> left(user does not exist)
of _, [el] -> right(el)
of _, _ -> left(internal server error)

Meaning if any of users is found, the function should return ReadonlyArray<User>> with either 2 or 1 users, and not throw error.

If there are 2 errors thrown meaning no user is found it should also return Error wrapped in TaskEither.

Sorry if my explanation is a bit blurry I'm still pretty new to fp-ts so please be kind to me :)

I've tried to use TE.fold and TE.chain but the issue is that I can't find the way to ignore error when one of calls return it

I tried:

F.pipe(
  TE.sequenceArray([fist, second]),
  TE.chain(successes => {
     if (successes.length > 0) {
        return TE.right(successes);
    } else {
      return TE.left(Error());
    }
  }),
  TE.map(results => results.flat()),
);

This solution seems to ignore my if statement

Share edited Mar 18 at 21:54 marc_s 756k184 gold badges1.4k silver badges1.5k bronze badges asked Jan 30 at 15:46 needithneedith 264 bronze badges 1
  • sequenceArray is the wrong tool for the job. It only returns the array result if all tasks succeeded. You cannot work with that. – Bergi Commented Mar 19 at 0:25
Add a comment  | 

1 Answer 1

Reset to default 1

As mentioned in the comments, TE.sequenceArray is not what you want. You could instead drop down to Task's sequenceArray:

import * as E from 'fp-ts/Either'
import * as F from 'fp-ts/function'
import * as O from 'fp-ts/Option'
import * as RA from 'fp-ts/ReadonlyArray'
import * as RNEA from 'fp-ts/ReadonlyNonEmptyArray'
import * as T from 'fp-ts/Task'
import * as TE from 'fp-ts/TaskEither'

class User {}
declare const first: TE.TaskEither<Error, User>
declare const second: TE.TaskEither<Error, User>

const result: TE.TaskEither<
  'user does not exist',
  RNEA.ReadonlyNonEmptyArray<User>
> = F.pipe(
  T.sequenceArray([first, second]),
  T.map(RA.filterMap(O.getRight)),
  T.map(RNEA.fromReadonlyArray),
  T.map(E.fromOption(() => 'user does not exist')),
)
转载请注明原文地址:http://anycun.com/QandA/1744908730a89328.html