Fp-ts: Either.mapLeft having incorrect type in pipe function that generates multiple types of lefts

Created on 17 May 2020  路  2Comments  路  Source: gcanti/fp-ts

馃悰 Bug report

Current Behavior

If I chain through Either in pipe function and if multiple types of lefts are generated, then parameter of Either.mapLeft should show a sum type of all those left types. It returns the type of the first left.

Reproducible example

const F = require("fp-ts");
const E = require("fp-ts/lib/Either");
const pipe = F.pipeable.pipe;

class TooBigError extends Error {};
class TooSmallError extends Error {}; 

pipe(
   E.right(2), 
   E.chain(num => num > 5 ? E.left(new TooBigError()) : E.right(num)),
   E.chain(num => num <= 5  ? E.left(new TooSmallError()) : E.right(num)),

   // err has the type `TooBigError` (the first `left` above)
   // it should have the type `TooBigError | TooSmallError` 
   E.mapLeft(err => console.log(err.constructor.name))
);

Expected behavior

err param in E.mapLeft should have a type of TooBigError | TooSmallError

| Software | Version(s) |
| ---------- | ---------- |
| fp-ts | 2.6.1 |
| TypeScript | 3.8.3 |

Most helpful comment

You can use chainW to widen the Left type:

import * as E from "fp-ts/lib/Either";
import { pipe } from "fp-ts/lib/pipeable";

class TooBigError extends Error {}
class TooSmallError extends Error {}

pipe(
  E.right(2),
  E.chain((num: number) =>
    num > 5 ? E.left(new TooBigError()) : E.right(num)
  ),
  E.chainW((num: number) =>
    num <= 5 ? E.left(new TooSmallError()) : E.right(num)
  ),

  // err has the type `TooBigError | TooSmallError`
  E.mapLeft(err => console.log(err.constructor.name))
);

Note that, however, TooBigError and TooSmallError are structurally equivalent, aka the same type for TS: I would consider tracking different errors at type level if possible

All 2 comments

You can use chainW to widen the Left type:

import * as E from "fp-ts/lib/Either";
import { pipe } from "fp-ts/lib/pipeable";

class TooBigError extends Error {}
class TooSmallError extends Error {}

pipe(
  E.right(2),
  E.chain((num: number) =>
    num > 5 ? E.left(new TooBigError()) : E.right(num)
  ),
  E.chainW((num: number) =>
    num <= 5 ? E.left(new TooSmallError()) : E.right(num)
  ),

  // err has the type `TooBigError | TooSmallError`
  E.mapLeft(err => console.log(err.constructor.name))
);

Note that, however, TooBigError and TooSmallError are structurally equivalent, aka the same type for TS: I would consider tracking different errors at type level if possible

@giogonzo is faster than me. I add only a couple of references: see https://github.com/gcanti/fp-ts/issues/1028 and https://github.com/gcanti/fp-ts/issues/904.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vicrac picture vicrac  路  4Comments

miguelferraro picture miguelferraro  路  3Comments

FredericLatour picture FredericLatour  路  3Comments

gcanti picture gcanti  路  3Comments

amaurymartiny picture amaurymartiny  路  4Comments