gcanti/fp-ts-contrib

Add W-variants to Do, e.g. bindLW

leemhenson opened this issue ยท 4 comments

๐Ÿš€ Feature request

Current Behavior

const foo = Do(TE.taskEither)
  .bind("te1", TE.right<boolean, number>(1))
  .bindL("te2", () => TE.right<string, string>("wat"));

fails with:

Type 'TaskEither<string, string>' is not assignable to type 'TaskEither<boolean, string>'.
Type 'string' is not assignable to type 'boolean'.ts(2322)

Desired Behavior

const foo = Do(TE.taskEither)
  .bind("te1", TE.right<boolean, number>(1))
  .bindLW("te2", () => TE.right<string, string>("wat"))
  .return(identity);

Where foo would be TaskEither<boolean | string, { te1: number} & { te2: string }>.

Suggested Solution

๐Ÿคทโ€โ™‚๏ธ Do is a complex beast.

Who does this impact? Who is this for?

This would alleviate the need to lift the first bind's Left into a union of all possible error types, which I believe is the current accepted workaround. This was the case for Either's chain too, until chainW was added recently. It would be great if we could get the same for Do.

Can you give some examples how I can use different error types with Do notation without W-variants?

Something like that?

type allErrors = Error1 | Error2;

Do(TE.taskEither)
  .bind(
    'result1',
    pipe(
      TE.right<Error1, number>(1),
      TE.mapLeft((err): allErrors => err),
    ),
  )
  .bind('result2', TE.right<Error2, number>(2));

I too have encountered this problem. My errors are a union of string constants, and it would be nice to have a bindW and bindLW that would allow the error type of the Do(TE.taskEither to be the union of all error types in the Do.

I recommend to use native fp-ts Do notaion - https://github.com/gcanti/fp-ts/releases/tag/2.8.0.