Skip to content

Revise 'left' and 'right' typings for typesafety #543

@sledorze

Description

@sledorze

Today's typing for 'left' and 'right' are unsafe due to the way typescript does it's inference and causing us some trouble.

Example:

export declare const left: <L, A>(l: L) => Either<L, A>;
export declare const right: <L, A>(a: A) => Either<L, A>;

const res = (cond: boolean) => (cond ? left(42) : right('what?')) // return type: Left<number, {}> | Right<number, {}> | Left<{}, string> | Right<{}, string>
const v = res(true)
if (v.isRight()) {
  v.value // string | {} (!! WRONG)
} else {
  v.value // number | {} (!! WRONG)
}

Thanks to the way union behave with never

type T = number | never // Type is number

With these typings inference works as expected

export declare const left: <L>(l: L) => Either<L, never>;
export declare const right: <A>(a: A) => Either<never, A>;

const res = (cond: boolean) => (cond ? left(42) : right('what?')) // return type: Left<number, never> | Right<number, never> | Left<never, string> | Right<never, string>
const v = res(true)
if (v.isRight()) {
  v.value // string (!! OK)
} else {
  v.value // number (!! OK)
}

I know this would be a breaking change,
so here's a backward compatible non breaking solution:

export declare const left: <L, A = never>(l: L) => Either<L, A>
export declare const right: <L = never, A = any>(a: A) => Either<L, typeof a>

Do you see any issue with it? (Being typesafe is priceless)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions