Free tools Windows power users keep installed
One-click scans. No signup required.
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
error-san lets TypeScript functions declare expected error cases and raise them with throw-like control flow, then converts the function’s outcome into data at a wrapper boundary. The tradeoff is explicit: callers get typed success and failure results, but the library does not provide error chaining or automatic propagation between wrapped functions.
What error-san changes about TypeScript errors
A function like getPost may promise to return a Post, even though fetching the post, checking the response status, or parsing JSON can fail. A signature that only says Promise<Post> does not describe those failure cases.
One way to make failures explicit is to return a Result value at each failure point. error-san takes another route: declare the expected error cases, raise one where it occurs, and wrap the function so its caller receives an outcome value rather than having to catch each expected failure as an ordinary thrown exception.
The approach will feel familiar if you have seen Rust’s Result, neverthrow, or Effect, but that is not a claim that these tools are equivalent. The distinction highlighted in jeem’s article is that error-san keeps throw-like raisers inside the function and converts the outcome at a boundary. Source: jeem, “error-san: typed errors without giving up throw”.
#1 Best Overall
How the declaration, raiser, and wrapper fit together
Declare the expected cases
The function declares its named error cases and payload types through an Errors<{...}> parameter. The errors parameter is supplied for the function’s use; the wrapper hides it from callers.
Raise an error where the failure occurs
A typed raiser can be called at the point where a condition fails. The article says these raisers return never: execution stops there, while TypeScript can preserve the type narrowing established by preceding checks. For example, a lookup can be expressed as posts.find(...) ?? errors.NotFoundError(); after the missing-post case is raised, the successful expression remains a Post.
Rank #2
- TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
- TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
- Lightweight, Classic fit, Double-needle sleeve and bottom hem
Wrap the function to return an outcome
Use wrapAsync for an asynchronous function or wrapSync for a synchronous one. The wrapper catches raised errors and makes the result available as data. A successful result exposes isOk and data; an error result exposes a code and the corresponding typed reason.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →According to the article, an unexpected throw or rejected promise is not erased: it becomes an UnexpectedError branch. The declared cases describe expected failures, not every failure that can occur at runtime.
Handling results and recovering from errors
Use unwrap when every declared case needs a branch
The article presents unwrap({ ... }) as an exhaustive handler map: TypeScript checks that the map covers the declared error cases and rejects invented cases. This makes the declared error contract useful at the call site, where a missing response to a known failure can be caught during type checking.
Use handle to recover from selected errors
The article also describes handle({ ... }) for recovery from selected errors. It is an option when a caller can resolve a particular failure rather than treating every error as an unrecoverable outcome.
What error-san does not automate
- No
maporandThenchains: the article says the library does not offer these composition methods. - No automatic propagation across wrapped functions: errors do not flow from one wrapped function into another by themselves. If a caller function needs to pass an error along, it must declare and re-raise that error.
- Raising has a runtime cost: the author says raising captures a stack trace and is more expensive than returning a value. That is a source-reported design claim, not an independent benchmark; measure if a raiser is on a performance-sensitive hot path.
These limits make the library’s tradeoff clearer: it favors typed declarations and throw-like control flow inside a function over a composable Result pipeline that carries errors through a chain automatically.
Compatibility, size, and installation claims
Jeem’s article says error-san has no runtime dependencies, runs in modern browsers, workers, and Node.js 22+, and requires TypeScript 7 or newer with strict enabled. Those are the article author’s claims; current compatibility has not been independently confirmed here, so check the project repository or package metadata before relying on them for a specific environment. The article also describes the package as under 1 kB minified and gzipped; that figure is likewise an author-reported claim, not an independent measurement.
Best Value
The article gives npm install error-san as the installation command and identifies an MIT license. Current package metadata and license status were not independently verified. It names the project repository as github.com/gohagoji/error-san.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

