Either.ts overview
Since v2.0.0
Exports Grouped by Category
- Optional Wrapping & Unwrapping
- combining
- constructors
- do notation
- equivalence
- error handling
- filtering & conditionals
- generators
- getters
- guards
- lifting
- mapping
- models
- pattern matching
- sequencing
- symbols
- type lambdas
- utils
- zipping
Optional Wrapping & Unwrapping
transposeMapOption
Applies an Either
on an Option
and transposes the result.
Details
If the Option
is None
, the resulting Either
will immediately succeed with a Right
value of None
. If the Option
is Some
, the transformation function will be applied to the inner value, and its result wrapped in a Some
.
Example
import { Either, Option, pipe } from "effect"
// ┌─── Either<Option<number>, never>>
// ▼
const noneResult = pipe(
Option.none(),
Either.transposeMapOption(() => Either.right(42)) // will not be executed
)
console.log(noneResult)
// Output: { _id: 'Either', _tag: 'Right', right: { _id: 'Option', _tag: 'None' } }
// ┌─── Either<Option<number>, never>>
// ▼
const someRightResult = pipe(
Option.some(42),
Either.transposeMapOption((value) => Either.right(value * 2))
)
console.log(someRightResult)
// Output: { _id: 'Either', _tag: 'Right', right: { _id: 'Option', _tag: 'Some', value: 84 } }
Signature
declare const transposeMapOption: (<A, B, E = never>(
f: (self: A) => Either<B, E>
) => (self: Option<A>) => Either<Option<B>, E>) &
(<A, B, E = never>(self: Option<A>, f: (self: A) => Either<B, E>) => Either<Option<B>, E>)
Since v3.15.0
transposeOption
Converts an Option
of an Either
into an Either
of an Option
.
Details
This function transforms an Option<Either<A, E>>
into an Either<Option<A>, E>
. If the Option
is None
, the resulting Either
will be a Right
with a None
value. If the Option
is Some
, the inner Either
will be executed, and its result wrapped in a Some
.
Example
import { Effect, Either, Option } from "effect"
// ┌─── Option<Either<number, never>>
// ▼
const maybe = Option.some(Either.right(42))
// ┌─── Either<Option<number>, never, never>
// ▼
const result = Either.transposeOption(maybe)
console.log(Effect.runSync(result))
// Output: { _id: 'Option', _tag: 'Some', value: 42 }
Signature
declare const transposeOption: <A = never, E = never>(self: Option<Either<A, E>>) => Either<Option<A>, E>
Since v3.14.0
combining
all
Takes a structure of Either
s and returns an Either
of values with the same structure.
- If a tuple is supplied, then the returned
Either
will contain a tuple with the same length. - If a struct is supplied, then the returned
Either
will contain a struct with the same keys. - If an iterable is supplied, then the returned
Either
will contain an array.
Example
import * as assert from "node:assert"
import { Either } from "effect"
assert.deepStrictEqual(Either.all([Either.right(1), Either.right(2)]), Either.right([1, 2]))
assert.deepStrictEqual(
Either.all({ right: Either.right(1), b: Either.right("hello") }),
Either.right({ right: 1, b: "hello" })
)
assert.deepStrictEqual(Either.all({ right: Either.right(1), b: Either.left("error") }), Either.left("error"))
Signature
declare const all: <const I extends Iterable<Either<any, any>> | Record<string, Either<any, any>>>(
input: I
) => [I] extends [ReadonlyArray<Either<any, any>>]
? Either<
{ -readonly [K in keyof I]: [I[K]] extends [Either<infer A, any>] ? A : never },
I[number] extends never ? never : [I[number]] extends [Either<any, infer E>] ? E : never
>
: [I] extends [Iterable<Either<infer A, infer E>>]
? Either<Array<A>, E>
: Either<
{ -readonly [K in keyof I]: [I[K]] extends [Either<infer A, any>] ? A : never },
I[keyof I] extends never ? never : [I[keyof I]] extends [Either<any, infer E>] ? E : never
>
Since v2.0.0
ap
Signature
declare const ap: {
<A, E2>(that: Either<A, E2>): <A2, E>(self: Either<(right: A) => A2, E>) => Either<A2, E | E2>
<A, A2, E, E2>(self: Either<(right: A) => A2, E>, that: Either<A, E2>): Either<A2, E | E2>
}
Since v2.0.0
constructors
fromNullable
Takes a lazy default and a nullable value, if the value is not nully (null
or undefined
), turn it into a Right
, if the value is nully use the provided default as a Left
.
Example
import * as assert from "node:assert"
import { Either } from "effect"
assert.deepStrictEqual(
Either.fromNullable(1, () => "fallback"),
Either.right(1)
)
assert.deepStrictEqual(
Either.fromNullable(null, () => "fallback"),
Either.left("fallback")
)
Signature
declare const fromNullable: {
<A, E>(onNullable: (right: A) => E): (self: A) => Either<NonNullable<A>, E>
<A, E>(self: A, onNullable: (right: A) => E): Either<NonNullable<A>, E>
}
Since v2.0.0
fromOption
Example
import * as assert from "node:assert"
import { Either, Option } from "effect"
assert.deepStrictEqual(
Either.fromOption(Option.some(1), () => "error"),
Either.right(1)
)
assert.deepStrictEqual(
Either.fromOption(Option.none(), () => "error"),
Either.left("error")
)
Signature
declare const fromOption: {
<E>(onNone: () => E): <A>(self: Option<A>) => Either<A, E>
<A, E>(self: Option<A>, onNone: () => E): Either<A, E>
}
Since v2.0.0
left
Constructs a new Either
holding a Left
value. This usually represents a failure, due to the right-bias of this structure.
Signature
declare const left: <E>(e: E) => Either<never, E>
Since v2.0.0
right
Constructs a new Either
holding a Right
value. This usually represents a successful value due to the right bias of this structure.
Signature
declare const right: <A>(a: A) => Either<A>
Since v2.0.0
try
Imports a synchronous side-effect into a pure Either
value, translating any thrown exceptions into typed failed eithers creating with Either.left
.
Signature
declare const try: { <A, E>(options: { readonly try: LazyArg<A>; readonly catch: (error: unknown) => E; }): Either<A, E>; <A>(evaluate: LazyArg<A>): Either<A, unknown>; }
Since v2.0.0
void
Signature
declare const void: Either<void, never>
Since v3.13.0
do notation
Do
The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind
and let
.
Here’s how the do simulation works:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEither
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - Inside the do simulation scope, you can also use the
let
function to define variables and bind them to simple values
Example
import * as assert from "node:assert"
import { Either, pipe } from "effect"
const result = pipe(
Either.Do,
Either.bind("x", () => Either.right(2)),
Either.bind("y", () => Either.right(3)),
Either.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(result, Either.right({ x: 2, y: 3, sum: 5 }))
See
bind
bindTo
let
Signature
declare const Do: Either<{}, never>
Since v2.0.0
bind
The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind
and let
.
Here’s how the do simulation works:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEither
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - Inside the do simulation scope, you can also use the
let
function to define variables and bind them to simple values
Example
import * as assert from "node:assert"
import { Either, pipe } from "effect"
const result = pipe(
Either.Do,
Either.bind("x", () => Either.right(2)),
Either.bind("y", () => Either.right(3)),
Either.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(result, Either.right({ x: 2, y: 3, sum: 5 }))
See
Do
bindTo
let
Signature
declare const bind: {
<N extends string, A extends object, B, E2>(
name: Exclude<N, keyof A>,
f: (a: NoInfer<A>) => Either<B, E2>
): <E>(self: Either<A, E>) => Either<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E | E2>
<A extends object, E, N extends string, B, E2>(
self: Either<A, E>,
name: Exclude<N, keyof A>,
f: (a: NoInfer<A>) => Either<B, E2>
): Either<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E | E2>
}
Since v2.0.0
bindTo
The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind
and let
.
Here’s how the do simulation works:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEither
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - Inside the do simulation scope, you can also use the
let
function to define variables and bind them to simple values
Example
import * as assert from "node:assert"
import { Either, pipe } from "effect"
const result = pipe(
Either.Do,
Either.bind("x", () => Either.right(2)),
Either.bind("y", () => Either.right(3)),
Either.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(result, Either.right({ x: 2, y: 3, sum: 5 }))
See
Do
bind
let
Signature
declare const bindTo: {
<N extends string>(name: N): <A, E>(self: Either<A, E>) => Either<{ [K in N]: A }, E>
<A, E, N extends string>(self: Either<A, E>, name: N): Either<{ [K in N]: A }, E>
}
Since v2.0.0
let
The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind
and let
.
Here’s how the do simulation works:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEither
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - Inside the do simulation scope, you can also use the
let
function to define variables and bind them to simple values
Example
import * as assert from "node:assert"
import { Either, pipe } from "effect"
const result = pipe(
Either.Do,
Either.bind("x", () => Either.right(2)),
Either.bind("y", () => Either.right(3)),
Either.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(result, Either.right({ x: 2, y: 3, sum: 5 }))
See
Do
bindTo
bind
Signature
declare const let: {
<N extends string, A extends object, B>(
name: Exclude<N, keyof A>,
f: (r: NoInfer<A>) => B
): <E>(self: Either<A, E>) => Either<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E>
<A extends object, E, N extends string, B>(
self: Either<A, E>,
name: Exclude<N, keyof A>,
f: (r: NoInfer<A>) => B
): Either<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E>
}
Since v2.0.0
equivalence
getEquivalence
Signature
declare const getEquivalence: <A, E>({
left,
right
}: {
right: Equivalence.Equivalence<A>
left: Equivalence.Equivalence<E>
}) => Equivalence.Equivalence<Either<A, E>>
Since v2.0.0
error handling
orElse
Returns self
if it is a Right
or that
otherwise.
Signature
declare const orElse: {
<E, A2, E2>(that: (left: E) => Either<A2, E2>): <A>(self: Either<A, E>) => Either<A | A2, E2>
<A, E, A2, E2>(self: Either<A, E>, that: (left: E) => Either<A2, E2>): Either<A | A2, E2>
}
Since v2.0.0
filtering & conditionals
filterOrLeft
Filter the right value with the provided function. If the predicate fails, set the left value with the result of the provided function.
Example
import * as assert from "node:assert"
import { pipe, Either } from "effect"
const isPositive = (n: number): boolean => n > 0
assert.deepStrictEqual(
pipe(
Either.right(1),
Either.filterOrLeft(isPositive, (n) => `${n} is not positive`)
),
Either.right(1)
)
assert.deepStrictEqual(
pipe(
Either.right(0),
Either.filterOrLeft(isPositive, (n) => `${n} is not positive`)
),
Either.left("0 is not positive")
)
Signature
declare const filterOrLeft: {
<A, B extends A, E2>(
refinement: Refinement<NoInfer<A>, B>,
orLeftWith: (right: NoInfer<A>) => E2
): <E>(self: Either<A, E>) => Either<B, E2 | E>
<A, E2>(
predicate: Predicate<NoInfer<A>>,
orLeftWith: (right: NoInfer<A>) => E2
): <E>(self: Either<A, E>) => Either<A, E2 | E>
<A, E, B extends A, E2>(
self: Either<A, E>,
refinement: Refinement<A, B>,
orLeftWith: (right: A) => E2
): Either<B, E | E2>
<A, E, E2>(self: Either<A, E>, predicate: Predicate<A>, orLeftWith: (right: A) => E2): Either<A, E | E2>
}
Since v2.0.0
generators
gen
Signature
declare const gen: Gen.Gen<EitherTypeLambda, Gen.Adapter<EitherTypeLambda>>
Since v2.0.0
getters
getLeft
Converts a Either
to an Option
discarding the value.
Example
import * as assert from "node:assert"
import { Either, Option } from "effect"
assert.deepStrictEqual(Either.getLeft(Either.right("ok")), Option.none())
assert.deepStrictEqual(Either.getLeft(Either.left("err")), Option.some("err"))
Signature
declare const getLeft: <A, E>(self: Either<A, E>) => Option<E>
Since v2.0.0
getOrElse
Returns the wrapped value if it’s a Right
or a default value if is a Left
.
Example
import * as assert from "node:assert"
import { Either } from "effect"
assert.deepStrictEqual(
Either.getOrElse(Either.right(1), (error) => error + "!"),
1
)
assert.deepStrictEqual(
Either.getOrElse(Either.left("not a number"), (error) => error + "!"),
"not a number!"
)
Signature
declare const getOrElse: {
<E, A2>(onLeft: (left: E) => A2): <A>(self: Either<A, E>) => A2 | A
<A, E, A2>(self: Either<A, E>, onLeft: (left: E) => A2): A | A2
}
Since v2.0.0
getOrNull
Example
import * as assert from "node:assert"
import { Either } from "effect"
assert.deepStrictEqual(Either.getOrNull(Either.right(1)), 1)
assert.deepStrictEqual(Either.getOrNull(Either.left("a")), null)
Signature
declare const getOrNull: <A, E>(self: Either<A, E>) => A | null
Since v2.0.0
getOrThrow
Extracts the value of an Either
or throws if the Either
is Left
.
The thrown error is a default error. To configure the error thrown, see getOrThrowWith
.
Throws
Error("getOrThrow called on a Left")
Example
import * as assert from "node:assert"
import { Either } from "effect"
assert.deepStrictEqual(Either.getOrThrow(Either.right(1)), 1)
assert.throws(() => Either.getOrThrow(Either.left("error")))
Signature
declare const getOrThrow: <A, E>(self: Either<A, E>) => A
Since v2.0.0
getOrThrowWith
Extracts the value of an Either
or throws if the Either
is Left
.
If a default error is sufficient for your use case and you don’t need to configure the thrown error, see getOrThrow
.
Example
import * as assert from "node:assert"
import { Either } from "effect"
assert.deepStrictEqual(
Either.getOrThrowWith(Either.right(1), () => new Error("Unexpected Left")),
1
)
assert.throws(() => Either.getOrThrowWith(Either.left("error"), () => new Error("Unexpected Left")))
Signature
declare const getOrThrowWith: {
<E>(onLeft: (left: E) => unknown): <A>(self: Either<A, E>) => A
<A, E>(self: Either<A, E>, onLeft: (left: E) => unknown): A
}
Since v2.0.0
getOrUndefined
Example
import * as assert from "node:assert"
import { Either } from "effect"
assert.deepStrictEqual(Either.getOrUndefined(Either.right(1)), 1)
assert.deepStrictEqual(Either.getOrUndefined(Either.left("a")), undefined)
Signature
declare const getOrUndefined: <A, E>(self: Either<A, E>) => A | undefined
Since v2.0.0
getRight
Converts a Either
to an Option
discarding the Left
.
Example
import * as assert from "node:assert"
import { Either, Option } from "effect"
assert.deepStrictEqual(Either.getRight(Either.right("ok")), Option.some("ok"))
assert.deepStrictEqual(Either.getRight(Either.left("err")), Option.none())
Signature
declare const getRight: <A, E>(self: Either<A, E>) => Option<A>
Since v2.0.0
merge
Signature
declare const merge: <A, E>(self: Either<A, E>) => E | A
Since v2.0.0
guards
isEither
Tests if a value is a Either
.
Example
import * as assert from "node:assert"
import { Either } from "effect"
assert.deepStrictEqual(Either.isEither(Either.right(1)), true)
assert.deepStrictEqual(Either.isEither(Either.left("a")), true)
assert.deepStrictEqual(Either.isEither({ right: 1 }), false)
Signature
declare const isEither: (input: unknown) => input is Either<unknown, unknown>
Since v2.0.0
isLeft
Determine if a Either
is a Left
.
Example
import * as assert from "node:assert"
import { Either } from "effect"
assert.deepStrictEqual(Either.isLeft(Either.right(1)), false)
assert.deepStrictEqual(Either.isLeft(Either.left("a")), true)
Signature
declare const isLeft: <A, E>(self: Either<A, E>) => self is Left<E, A>
Since v2.0.0
isRight
Determine if a Either
is a Right
.
Example
import * as assert from "node:assert"
import { Either } from "effect"
assert.deepStrictEqual(Either.isRight(Either.right(1)), true)
assert.deepStrictEqual(Either.isRight(Either.left("a")), false)
Signature
declare const isRight: <A, E>(self: Either<A, E>) => self is Right<E, A>
Since v2.0.0
lifting
liftPredicate
Transforms a Predicate
function into a Right
of the input value if the predicate returns true
or Left
of the result of the provided function if the predicate returns false
Example
import * as assert from "node:assert"
import { pipe, Either } from "effect"
const isPositive = (n: number): boolean => n > 0
const isPositiveEither = Either.liftPredicate(isPositive, (n) => `${n} is not positive`)
assert.deepStrictEqual(isPositiveEither(1), Either.right(1))
assert.deepStrictEqual(isPositiveEither(0), Either.left("0 is not positive"))
Signature
declare const liftPredicate: {
<A, B extends A, E>(refinement: Refinement<A, B>, orLeftWith: (a: A) => E): (a: A) => Either<B, E>
<B extends A, E, A = B>(predicate: Predicate<A>, orLeftWith: (a: A) => E): (a: B) => Either<B, E>
<A, E, B extends A>(self: A, refinement: Refinement<A, B>, orLeftWith: (a: A) => E): Either<B, E>
<B extends A, E, A = B>(self: B, predicate: Predicate<A>, orLeftWith: (a: A) => E): Either<B, E>
}
Since v3.4.0
mapping
flip
Returns an Either
that swaps the error/success cases. This allows you to use all methods on the error channel, possibly before flipping back.
Signature
declare const flip: <A, E>(self: Either<A, E>) => Either<E, A>
Since v2.0.0
map
Maps the Right
side of an Either
value to a new Either
value.
Signature
declare const map: {
<A, A2>(f: (right: A) => A2): <E>(self: Either<A, E>) => Either<A2, E>
<A, E, A2>(self: Either<A, E>, f: (right: A) => A2): Either<A2, E>
}
Since v2.0.0
mapBoth
Signature
declare const mapBoth: {
<E, E2, A, A2>(options: {
readonly onLeft: (left: E) => E2
readonly onRight: (right: A) => A2
}): (self: Either<A, E>) => Either<A2, E2>
<A, E, E2, A2>(
self: Either<A, E>,
options: { readonly onLeft: (left: E) => E2; readonly onRight: (right: A) => A2 }
): Either<A2, E2>
}
Since v2.0.0
mapLeft
Maps the Left
side of an Either
value to a new Either
value.
Signature
declare const mapLeft: {
<E, E2>(f: (left: E) => E2): <A>(self: Either<A, E>) => Either<A, E2>
<A, E, E2>(self: Either<A, E>, f: (left: E) => E2): Either<A, E2>
}
Since v2.0.0
models
Either (type alias)
Signature
type Either<A, E> = Left<E, A> | Right<E, A>
Since v2.0.0
EitherUnify (interface)
Signature
export interface EitherUnify<A extends { [Unify.typeSymbol]?: any }> {
Either?: () => A[Unify.typeSymbol] extends Either<infer R0, infer L0> | infer _ ? Either<R0, L0> : never
}
Since v2.0.0
EitherUnifyIgnore (interface)
Signature
export interface EitherUnifyIgnore {}
Since v2.0.0
Left (interface)
Signature
export interface Left<out E, out A> extends Pipeable, Inspectable {
readonly _tag: "Left"
readonly _op: "Left"
readonly left: E
readonly [TypeId]: {
readonly _R: Covariant<A>
readonly _L: Covariant<E>
}
[Unify.typeSymbol]?: unknown
[Unify.unifySymbol]?: EitherUnify<this>
[Unify.ignoreSymbol]?: EitherUnifyIgnore
}
Since v2.0.0
Right (interface)
Signature
export interface Right<out E, out A> extends Pipeable, Inspectable {
readonly _tag: "Right"
readonly _op: "Right"
readonly right: A
readonly [TypeId]: {
readonly _R: Covariant<A>
readonly _L: Covariant<E>
}
[Unify.typeSymbol]?: unknown
[Unify.unifySymbol]?: EitherUnify<this>
[Unify.ignoreSymbol]?: EitherUnifyIgnore
}
Since v2.0.0
pattern matching
match
Takes two functions and an Either
value, if the value is a Left
the inner value is applied to the onLeft function, if the value is a
Rightthe inner value is applied to the
onRight` function.
Example
import * as assert from "node:assert"
import { pipe, Either } from "effect"
const onLeft = (strings: ReadonlyArray<string>): string => `strings: ${strings.join(", ")}`
const onRight = (value: number): string => `Ok: ${value}`
assert.deepStrictEqual(pipe(Either.right(1), Either.match({ onLeft, onRight })), "Ok: 1")
assert.deepStrictEqual(
pipe(Either.left(["string 1", "string 2"]), Either.match({ onLeft, onRight })),
"strings: string 1, string 2"
)
Signature
declare const match: {
<E, B, A, C = B>(options: {
readonly onLeft: (left: E) => B
readonly onRight: (right: A) => C
}): (self: Either<A, E>) => B | C
<A, E, B, C = B>(
self: Either<A, E>,
options: { readonly onLeft: (left: E) => B; readonly onRight: (right: A) => C }
): B | C
}
Since v2.0.0
sequencing
andThen
Executes a sequence of two Either
s. The second Either
can be dependent on the result of the first Either
.
Signature
declare const andThen: {
<A, A2, E2>(f: (right: A) => Either<A2, E2>): <E>(self: Either<A, E>) => Either<A2, E | E2>
<A2, E2>(f: Either<A2, E2>): <E, A>(self: Either<A, E>) => Either<A2, E | E2>
<A, A2>(f: (right: A) => A2): <E>(self: Either<A, E>) => Either<A2, E>
<A2>(right: NotFunction<A2>): <A, E>(self: Either<A, E>) => Either<A2, E>
<A, E, A2, E2>(self: Either<A, E>, f: (right: A) => Either<A2, E2>): Either<A2, E | E2>
<A, E, A2, E2>(self: Either<A, E>, f: Either<A2, E2>): Either<A2, E | E2>
<A, E, A2>(self: Either<A, E>, f: (right: A) => A2): Either<A2, E>
<A, E, A2>(self: Either<A, E>, f: NotFunction<A2>): Either<A2, E>
}
Since v2.0.0
flatMap
Signature
declare const flatMap: {
<A, A2, E2>(f: (right: A) => Either<A2, E2>): <E>(self: Either<A, E>) => Either<A2, E | E2>
<A, E, A2, E2>(self: Either<A, E>, f: (right: A) => Either<A2, E2>): Either<A2, E | E2>
}
Since v2.0.0
symbols
TypeId
Signature
declare const TypeId: unique symbol
Since v2.0.0
TypeId (type alias)
Signature
type TypeId = typeof TypeId
Since v2.0.0
type lambdas
EitherTypeLambda (interface)
Signature
export interface EitherTypeLambda extends TypeLambda {
readonly type: Either<this["Target"], this["Out1"]>
}
Since v2.0.0
utils
Either (namespace)
Since v2.0.0
Left (type alias)
Signature
type Left<T> = [T] extends [Either<infer _A, infer _E>] ? _E : never
Since v2.0.0
Right (type alias)
Signature
type Right<T> = [T] extends [Either<infer _A, infer _E>] ? _A : never
Since v2.0.0
zipping
zipWith
Signature
declare const zipWith: {
<A2, E2, A, B>(that: Either<A2, E2>, f: (right: A, right2: A2) => B): <E>(self: Either<A, E>) => Either<B, E2 | E>
<A, E, A2, E2, B>(self: Either<A, E>, that: Either<A2, E2>, f: (right: A, right2: A2) => B): Either<B, E | E2>
}
Since v2.0.0