Branching `if` statement in `Either.chainW` doesn't union properly
Author: atomanyihCreated Apr 28, 2022Updated Oct 11, 2024
Bug report
Current Behavior
Note: example has been replaced with a more representative case
type StoreError = {
type: 'storeError';
excuse: string;
};
type Hotdog = {
type: 'hotdog';
length: 'small' | 'medium' | 'large';
name: string;
};
const getHotdog = (length: Hotdog['length']): E.Either<StoreError, Hotdog> => {
return E.of({
type: 'hotdog',
length,
name: 'Cindy',
})
}
type Sausage = {
type: 'sausage';
length: 'small' | 'medium' | 'large';
name: string;
};
const getSausage = (length: Sausage['length']): E.Either<StoreError, Sausage> => {
return E.of({
type: 'sausage',
length,
name: 'Addison',
})
}
function getMediumHotdogOrSausage(type: 'hotdog' | 'sausage') {
return pipe(
E.of(type),
E.chainW((type) => {
// TS2345: Argument of type '(type: "hotdog" | "sausage") => Left<StoreError> | Right<Hotdog> | Right<Sausage>' is not assignable to parameter of type '(a: "hotdog" | "sausage") => Either<StoreError, Hotdog>'.
// Type 'Left<StoreError> | Right<Hotdog> | Right<Sausage>' is not assignable to type 'Either<StoreError, Hotdog>'.
// Type 'Right<Sausage>' is not assignable to type 'Either<StoreError, Hotdog>'.
// Type 'Right<Sausage>' is not assignable to type 'Right<Hotdog>'.
// Type 'Sausage' is not assignable to type 'Hotdog'.
// Types of property 'type' are incompatible.
// Type '"sausage"' is not assignable to type '"hotdog"'.
if (type === 'hotdog') {
return getHotdog('medium');
}
return getSausage('small');
}),
);
}Expected behavior
I would expect this to pass type-check and result in a type E.Either<StoreError, Sausage | Hotdog>.
Is there a better way to represent a branch like this?
Your environment
Which versions of fp-ts are affected by this issue? Did this work in previous versions of fp-ts?
| Software | Version(s) |
|---|---|
| fp-ts | 2.11.8 |
| TypeScript | 4.5.5 |
Source: gcanti/fp-ts