error-san lets TypeScript functions declare expected error cases and raise them with throw-like control flow, then converts the outcome into data at a wrapper boundary. The tradeoff is deliberate: unexpected throws and rejections are represented as an UnexpectedError case, while callers must explicitly handle or re-raise declared errors they want to propagate.
What problem does error-san address?
A function’s TypeScript return type can promise a successful value without describing failures that happen while producing it. For example, getPost might be typed to return a Post, even though fetching the data can reject, an HTTP status check can fail, or JSON parsing can throw. Those failure paths are real, but they are not visible in the declared return type.
As an Amazon Associate I earn from qualifying purchases.
One way to make failures explicit is to return a Result value at each failure point. error-san takes a different approach: declare the expected error cases, raise one where it occurs, and wrap the function so its caller receives a success-or-error outcome as data. The author describes the approach as familiar in concept to developers who have used Rust’s Result, neverthrow, or Effect, but the function-body style is the distinction: error-san retains throw-like raisers rather than requiring a Result constructor at each failure site.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11How does the typed-raiser pattern work?
Declare the function’s expected failures
The function receives an Errors<{...}> parameter describing named error cases and their payload types. The wrapper hides this parameter from the external caller, so callers use the wrapped function rather than supplying an errors object themselves.
#1 Best Overall
Raise a declared error where the failure occurs
A typed raiser is used like a function call at the failure point. The author says these raisers return never: control flow stops there, and TypeScript can preserve narrowing on the success path. For example, a lookup can express a missing-post case as posts.find(...) ?? errors.NotFoundError(); after that expression, the successful value remains narrowed to Post.
Wrap the function to return an outcome
Use wrapAsync for an asynchronous function or wrapSync for a synchronous one. The wrapped call exposes an outcome rather than letting its declared failures escape as ordinary throws. The result provides isOk and data for success, or an error code and its corresponding typed reason for failure.
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
The wrapper is not a guarantee that nothing can throw. According to the article, expected typed raisers are caught as declared cases, while other thrown errors or rejected promises become an UnexpectedError branch. That distinction lets callers account for anticipated failures without claiming every possible failure has been predicted.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →How do callers handle errors?
Use unwrap for exhaustive handling
The article presents unwrap({ ... }) as a handler map checked against the function’s declared error cases. A handler map must cover the declared cases and cannot invent additional ones, according to the author. This makes the failure contract visible at the call site and helps TypeScript flag a missing case when the declaration changes.
The author contrasts this compile-time check with ordinary throw, which does not provide an equivalent exhaustive handler map. That benefit applies to the cases declared in the function contract; the separate UnexpectedError branch matters for failures outside that contract.
Use handle to recover selectively
The article also describes handle({ ... }) for recovering from selected errors. This is useful when a caller can resolve one particular failure locally while allowing other outcome cases to remain represented as failures.
What does error-san leave out?
- No
maporandThenchains: the author says the library does not provide these chaining methods. - No automatic error propagation across wrapped functions: a failure from one wrapped function does not automatically become a declared failure of another.
- Explicit re-raising at caller boundaries: a caller function must declare and re-raise the errors it intends to pass along.
- Raising has a cost: the author says raising captures a stack trace and is more expensive than returning a value. If a raiser is on a hot path, measure the impact in the application rather than assuming the cost is negligible.
These are design and performance statements reported by the article’s author, jeem; they are not independently tested findings here.
Free tools Windows power users keep installed
One-click scans. No signup required.
What setup and compatibility claims are established?
The article gives npm install error-san as the installation command and identifies an MIT license. It also claims the package has no runtime dependencies, works in modern browsers and workers and Node.js 22+, and is “under 1 kB minified and gzipped.” These details are author-reported claims, not independently confirmed current package metadata or measurements.
Best Value
The author’s stated TypeScript requirement is: “It needs TypeScript 7 or newer with strict on.” The source search result shows the article date as “Aug 18” without a year, so it does not establish when that compatibility statement was published. Verify the current requirements, license, package size, and runtime support against the project’s canonical repository or npm package metadata before relying on them for a new project.
The article identifies the project repository as github.com/gohagoji/error-san. Its stated compatibility should not be treated as independently verified current support solely on the basis of that article.
Is error-san a fit for a TypeScript codebase?
Its central appeal is for teams that want declared, typed failure cases and exhaustive handling but prefer throw-like control flow inside functions. Its boundary wrapper makes success or failure inspectable as data without requiring each expected failure site to return a Result constructor.
Recommended Free Tools
That style comes with explicit limits: there is no chaining API or automatic propagation, and errors cross function boundaries only when callers declare and re-raise them. The package’s current compatibility and performance characteristics should be checked against current project metadata and measured in the application where raising might be frequent.
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.




