When working with error handling in TypeScript, both neverthrow and Effect provide useful abstractions for modeling
success and failure without exceptions. They share many concepts, such as wrapping computations in a safe container,
transforming values with map, handling errors with mapErr/mapLeft, and offering utilities to combine or unwrap results.
This page shows a side-by-side comparison of neverthrow and Effect APIs for common use cases.
If you’re already familiar with neverthrow, the examples will help you understand how to achieve the same patterns with Effect.
If you’re starting fresh, the comparison highlights the similarities and differences so you can decide which library better fits your project.
neverthrow exposes instance methods (for example, result.map(...)).
Effect exposes functions on Either (for example, Either.map(result, ...)) and supports a pipe style for readability and better tree shaking.
Synchronous API
ok
Example (Creating a success result)
1
import {
import ok
ok } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
2
3
const
constresult:any
result=
import ok
ok({
myData: string
myData: "test" })
4
5
constresult:any
result.
any
isOk() // true
6
constresult:any
result.
any
isErr() // false
1
import*as
import Either
Eitherfrom"effect/Either"
Error ts(2307) ― Cannot find module 'effect/Either' or its corresponding type declarations.
2
3
const
constresult:any
result=
import Either
Either.
any
right({
myData: string
myData: "test" })
4
5
import Either
Either.
any
isRight(
constresult:any
result) // true
6
import Either
Either.
any
isLeft(
constresult:any
result) // false
err
Example (Creating a failure result)
1
import {
import err
err } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
2
3
const
constresult:any
result=
import err
err("Oh no")
4
5
constresult:any
result.
any
isOk() // false
6
constresult:any
result.
any
isErr() // true
1
import*as
import Either
Eitherfrom"effect/Either"
Error ts(2307) ― Cannot find module 'effect/Either' or its corresponding type declarations.
2
3
const
constresult:any
result=
import Either
Either.
any
left("Oh no")
4
5
import Either
Either.
any
isRight(
constresult:any
result) // false
6
import Either
Either.
any
isLeft(
constresult:any
result) // true
map
Example (Transforming the success value)
1
import {
import Result
Result } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
Error ts(7006) ― Parameter 'kvMap' implicitly has an 'any' type.
17
import Effect
Effect.andThen((
authorization: unknown
authorization) =>
Error ts(2769) ― No overload matches this call.
Overload 1 of 4, '(f: (a: unknown) => Effect<unknown, unknown, unknown>): <E, R>(self: Effect<unknown, E, R>) => Effect<unknown, unknown, unknown>', gave the following error.
Type 'Promise<User | undefined>' is missing the following properties from type 'Effect<unknown, unknown, unknown>': [TypeId], [Symbol.iterator], pipe, toJSON, [NodeInspectSymbol]
Overload 2 of 4, '(f: Effect<unknown, unknown, unknown>): <A, E, R>(self: Effect<A, E, R>) => Effect<unknown, unknown, unknown>', gave the following error.
Argument of type '(authorization: unknown) => Promise<User | undefined>' is not assignable to parameter of type 'Effect<unknown, unknown, unknown>'.
Error ts(2345) ― Argument of type '{} | null' is not assignable to parameter of type 'string'.
Type 'null' is not assignable to type 'string'.
21
),
22
)
Note. In neverthrow, asyncMap works with Promises directly.
In Effect, passing a Promise to combinators like Effect.andThen automatically lifts it into an Effect.
If the Promise rejects, the rejection is turned into an UnknownException, which is why the error type is widened to string | UnknownException.
combine
Example (Combining multiple results)
1
import {
import Result
Result,
import ok
ok } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
2
3
const
constresults:Result<number, string>[]
results:
import Result
Result<number, string>[] = [
import ok
ok(1),
import ok
ok(2)]
4
5
// const combined: Result<number[], string>
6
const
constcombined:any
combined=
import Result
Result.
any
combine(
constresults:Result<number, string>[]
results)
1
import*as
import Either
Eitherfrom"effect/Either"
Error ts(2307) ― Cannot find module 'effect/Either' or its corresponding type declarations.
2
3
const
constresults:Either.Either<number, string>[]
results:
import Either
Either.
typeEither.Either =/*unresolved*/any
Either<number, string>[] = [
4
import Either
Either.
any
right(1),
5
import Either
Either.
any
right(2),
6
]
7
8
// const combined: Either<number[], string>
9
const
constcombined:any
combined=
import Either
Either.
any
all(
constresults:Either.Either<number, string>[]
results)
combineWithAllErrors
Example (Collecting all errors and successes)
1
import {
import Result
Result,
import ok
ok,
import err
err } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
2
3
const
constresults:Result<number, string>[]
results:
import Result
Result<number, string>[] = [
4
import ok
ok(123),
5
import err
err("boooom!"),
6
import ok
ok(456),
7
import err
err("ahhhhh!"),
8
]
9
10
const
constresult:any
result=
import Result
Result.
any
combineWithAllErrors(
constresults:Result<number, string>[]
results)
11
// result is Err(['boooom!', 'ahhhhh!'])
1
import*as
import Either
Eitherfrom"effect/Either"
Error ts(2307) ― Cannot find module 'effect/Either' or its corresponding type declarations.
2
import*as
import Array
Arrayfrom"effect/Array"
3
4
const
constresults:Either.Either<number, string>[]
results:
import Either
Either.
typeEither.Either =/*unresolved*/any
Either<number, string>[] = [
5
import Either
Either.
any
right(123),
6
import Either
Either.
any
left("boooom!"),
7
import Either
Either.
any
right(456),
8
import Either
Either.
any
left("ahhhhh!"),
9
]
10
11
const
consterrors:any
errors=
import Array
Array.getLefts(
constresults:Either.Either<number, string>[]
results)
Error ts(2339) ― Property 'getLefts' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Array")'.
12
// errors is ['boooom!', 'ahhhhh!']
13
14
const
constsuccesses:any
successes=
import Array
Array.getRights(
constresults:Either.Either<number, string>[]
results)
Error ts(2339) ― Property 'getRights' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Array")'.
15
// successes is [123, 456]
Note. There is no exact equivalent of Result.combineWithAllErrors in Effect.
Use Array.getLefts to collect all errors and Array.getRights to collect all successes.
Asynchronous API
In the examples below we use Effect.runPromise to run an effect and return a Promise.
You can also use other APIs such as Effect.runPromiseExit, which can capture additional cases like defects (runtime errors) and interruptions.
okAsync
Example (Creating a successful async result)
1
import {
import okAsync
okAsync } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
2
3
const
constmyResultAsync:any
myResultAsync=
import okAsync
okAsync({
myData: string
myData: "test" })
4
5
const
constresult:any
result=await
constmyResultAsync:any
myResultAsync
6
7
constresult:any
result.
any
isOk() // true
8
constresult:any
result.
any
isErr() // false
1
import*as
import Either
Eitherfrom"effect/Either"
Error ts(2307) ― Cannot find module 'effect/Either' or its corresponding type declarations.
Error ts(2339) ― Property 'either' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Effect")'.
7
8
import Either
Either.
any
isRight(
constresult:unknown
result) // true
9
import Either
Either.
any
isLeft(
constresult:unknown
result) // false
errAsync
Example (Creating a failed async result)
1
import {
import errAsync
errAsync } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
2
3
const
constmyResultAsync:any
myResultAsync=
import errAsync
errAsync("Oh no")
4
5
const
constmyResult:any
myResult=await
constmyResultAsync:any
myResultAsync
6
7
constmyResult:any
myResult.
any
isOk() // false
8
constmyResult:any
myResult.
any
isErr() // true
1
import*as
import Either
Eitherfrom"effect/Either"
Error ts(2307) ― Cannot find module 'effect/Either' or its corresponding type declarations.
Error ts(2339) ― Property 'either' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Effect")'.
7
8
import Either
Either.
any
isRight(
constresult:unknown
result) // false
9
import Either
Either.
any
isLeft(
constresult:unknown
result) // true
fromThrowable
Example (Wrapping a Promise-returning function that may throw)
1
import {
import ResultAsync
ResultAsync } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
2
3
interface
interfaceUser
User {}
4
declarefunction
functioninsertIntoDb(user:User):Promise<User>
insertIntoDb(
user: User
user:
interfaceUser
User):
interfacePromise<T>
Promise<
interfaceUser
User>
5
6
// (user: User) => ResultAsync<User, Error>
7
const
constinsertUser:any
insertUser=
import ResultAsync
ResultAsync.
any
fromThrowable(
8
functioninsertIntoDb(user:User):Promise<User>
insertIntoDb,
9
() =>new
var Error:ErrorConstructor
new (message?:string, options?:ErrorOptions) =>Error (+1 overload)
Error ts(2339) ― Property 'either' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Effect")'.
17
(
namesResult: Either.Either<string[], Error>
namesResult:
import Either
Either.
typeEither.Either =/*unresolved*/any
Either<
interfaceArray<T>
Array<string>,
interfaceError
Error>) => {
18
if (
import Either
Either.
any
isLeft(
namesResult: Either.Either<string[], Error>
namesResult)) {
19
var console:Console
console.
Console.log(...data: any[]): void
log("Couldn't get the users from the database",
namesResult: Either.Either<string[], Error>
namesResult.
any
left)
20
} else {
21
var console:Console
console.
Console.log(...data: any[]): void
log("Users in Canada are named: "+
namesResult: Either.Either<string[], Error>
namesResult.
any
right.
any
join(","))
22
}
23
},
24
)
mapErr
Example (Transforming the error value)
1
import {
import Result
Result,
import ResultAsync
ResultAsync } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
Error ts(2339) ― Property 'either' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Effect")'.
21
(
usersResult: Either.Either<User[], string>
usersResult:
import Either
Either.
typeEither.Either =/*unresolved*/any
Either<
interfaceArray<T>
Array<
interfaceUser
User>, string>) => {
22
if (
import Either
Either.
any
isLeft(
usersResult: Either.Either<User[], string>
usersResult)) {
23
var console:Console
console.
Console.log(...data: any[]): void
log("Couldn't get the users from the database",
usersResult: Either.Either<User[], string>
usersResult.
any
left)
24
} else {
25
var console:Console
console.
Console.log(...data: any[]): void
log("Users in Canada are: "+
usersResult: Either.Either<User[], string>
usersResult.
any
right.
any
join(","))
26
}
27
},
28
)
unwrapOr
Example (Providing a default value when async fails)
1
import {
import errAsync
errAsync } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
Error ts(2339) ― Property 'either' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Effect")'.
17
(
res: Either.Either<void, Error>
res:
import Either
Either.
typeEither.Either =/*unresolved*/any
Either<void,
interfaceError
Error>) => {
18
if (
import Either
Either.
any
isLeft(
res: Either.Either<void, Error>
res)) {
19
var console:Console
console.
Console.log(...data: any[]): void
log("Oops, at least one step failed",
res: Either.Either<void, Error>
res.
any
left)
20
} else {
21
var console:Console
console.
Console.log(...data: any[]): void
log(
22
"User has been validated, inserted and notified successfully.",
23
)
24
}
25
},
26
)
orElse
Example (Fallback when an async operation fails)
1
import {
import ResultAsync
ResultAsync,
import ok
ok } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
Error ts(2339) ― Property 'orElse' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Effect")'.
Error ts(2339) ― Property 'either' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Effect")'.
16
if (
import Either
Either.
any
isRight(
result: unknown
result)) {
17
var console:Console
console.
Console.log(...data: any[]): void
log("User data:", result.
any
right)
Error ts(18046) ― 'result' is of type 'unknown'.
18
}
19
})
match
Example (Handling success and failure at the end of a chain)
1
import {
import ResultAsync
ResultAsync } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
Error ts(2339) ― Property 'either' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Effect")'.
Error ts(2551) ― Property 'validateAll' does not exist on type 'typeof import("/home/runner/work/website/website/node_modules/.pnpm/effect@4.0.0-rc.115/node_modules/effect/dist/Effect")'. Did you mean 'validate'?
12
)
13
// result is left(['boooom!', 'ahhhhh!'])
Utilities
fromThrowable
Example (Safely wrapping a throwing function)
1
import {
import Result
Result } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
2
3
type
typeParseError= {
message:string;
}
ParseError= {
message: string
message:string }
4
const
consttoParseError: () =>ParseError
toParseError= ():
typeParseError= {
message:string;
}
ParseError=> ({
message: string
message: "Parse Error" })
5
6
const
constsafeJsonParse:any
safeJsonParse=
import Result
Result.
any
fromThrowable(
varJSON:JSON
JSON.
JSON.parse(text: string, reviver?: (this:any, key:string, value:any) => any): any
parse,
consttoParseError: () =>ParseError
toParseError)
7
8
// the function can now be used safely,
9
// if the function throws, the result will be an Err
10
const
constresult:any
result=
constsafeJsonParse:any
safeJsonParse("{")
1
import*as
import Either
Eitherfrom"effect/Either"
Error ts(2307) ― Cannot find module 'effect/Either' or its corresponding type declarations.
2
3
type
typeParseError= {
message:string;
}
ParseError= {
message: string
message:string }
4
const
consttoParseError: () =>ParseError
toParseError= ():
typeParseError= {
message:string;
}
ParseError=> ({
message: string
message: "Parse Error" })
5
6
const
constsafeJsonParse: (s:string) =>any
safeJsonParse= (
s: string
s:string) =>
7
import Either
Either.
any
try({
try: () => any
try: () =>
varJSON:JSON
JSON.
JSON.parse(text: string, reviver?: (this:any, key:string, value:any) => any): any
parse(
s: string
s),
catch: () => ParseError
catch:
consttoParseError: () =>ParseError
toParseError })
8
9
// the function can now be used safely,
10
// if the function throws, the result will be an Either
11
const
constresult:any
result=
constsafeJsonParse: (s:string) =>any
safeJsonParse("{")
safeTry
Example (Using generators to simplify error handling)
1
import {
import Result
Result,
import ok
ok,
import safeTry
safeTry } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
2
3
declarefunction
functionmayFail1():Result<number, string>
mayFail1():
import Result
Result<number, string>
4
declarefunction
functionmayFail2():Result<number, string>
mayFail2():
import Result
Result<number, string>
5
6
function
functionmyFunc():Result<number, string>
myFunc():
import Result
Result<number, string> {
7
return
import safeTry
safeTry<number, string>(function* () {
8
return
import ok
ok(
9
(yield*
functionmayFail1():Result<number, string>
mayFail1().
any
mapErr(
10
(e) =>`aborted by an error from 1st function, ${
e: any
e}`,
Error ts(7006) ― Parameter 'e' implicitly has an 'any' type.
11
)) +
12
(yield*
functionmayFail2():Result<number, string>
mayFail2().
any
mapErr(
13
(e) =>`aborted by an error from 2nd function, ${
e: any
e}`,
Error ts(7006) ― Parameter 'e' implicitly has an 'any' type.
14
)),
15
)
16
})
17
}
1
import*as
import Either
Eitherfrom"effect/Either"
Error ts(2307) ― Cannot find module 'effect/Either' or its corresponding type declarations.
2
3
declarefunction
functionmayFail1():Either.Either<number, string>
mayFail1():
import Either
Either.
typeEither.Either =/*unresolved*/any
Either<number, string>
4
declarefunction
functionmayFail2():Either.Either<number, string>
mayFail2():
import Either
Either.
typeEither.Either =/*unresolved*/any
Either<number, string>
5
6
function
functionmyFunc():Either.Either<number, string>
myFunc():
import Either
Either.
typeEither.Either =/*unresolved*/any
Either<number, string> {
7
return
import Either
Either.
any
gen(function* () {
8
return (
9
(yield*
functionmayFail1():Either.Either<number, string>
mayFail1().
any
pipe(
10
import Either
Either.
any
mapLeft((e) =>`aborted by an error from 1st function, ${
e: any
e}`),
Error ts(7006) ― Parameter 'e' implicitly has an 'any' type.
11
)) +
12
(yield*
functionmayFail2():Either.Either<number, string>
mayFail2().
any
pipe(
13
import Either
Either.
any
mapLeft((e) =>`aborted by an error from 2nd function, ${
e: any
e}`),
Error ts(7006) ― Parameter 'e' implicitly has an 'any' type.
14
))
15
)
16
})
17
}
Note. With Either.gen, you do not need to wrap the final value with Either.right. The generator’s return value becomes the Right.
You can also use an async generator function with safeTry to represent an asynchronous block.
On the Effect side, the same pattern is written with Effect.gen instead of Either.gen.
Example (Using async generators to handle multiple failures)
1
import {
import ResultAsync
ResultAsync,
import safeTry
safeTry,
import ok
ok } from"neverthrow"
Error ts(2307) ― Cannot find module 'neverthrow' or its corresponding type declarations.
2
3
declarefunction
functionmayFail1():ResultAsync<number, string>
mayFail1():
import ResultAsync
ResultAsync<number, string>
4
declarefunction
functionmayFail2():ResultAsync<number, string>
mayFail2():
import ResultAsync
ResultAsync<number, string>
5
6
function
functionmyFunc():ResultAsync<number, string>
myFunc():
import ResultAsync
ResultAsync<number, string> {
7
return
import safeTry
safeTry<number, string>(asyncfunction* () {
8
return
import ok
ok(
9
(yield*
functionmayFail1():ResultAsync<number, string>
mayFail1().
any
mapErr(
10
(e) =>`aborted by an error from 1st function, ${
e: any
e}`,
Error ts(7006) ― Parameter 'e' implicitly has an 'any' type.
11
)) +
12
(yield*
functionmayFail2():ResultAsync<number, string>
mayFail2().
any
mapErr(
13
(e) =>`aborted by an error from 2nd function, ${
e: any
e}`,
Error ts(7006) ― Parameter 'e' implicitly has an 'any' type.