Define your errors. Throw them like normal. The tooling catches what you miss.
npm install faultline
Both paths use the same error definitions. Start simple and level up, or jump straight into the full system.
Keep your existing patterns. Define typed errors, throw them, and let the ESLint plugin catch your mistakes.
throw UserErrors.NotFound({ userId: id });
// catch — fully typed
if (isErrorTag(e, UserErrors.NotFound)) {
e.data.userId // string
e.status // 404
}
throw new Error().toJSON() serializationCompiler-tracked errors through your entire pipeline. Exhaustive matching, error boundaries, and typed recovery.
getUser(userId)
.andThen(user => chargeCard(user, amount))
.match({
ok: (receipt) => ({ status: 200 }),
'User.NotFound': (e) => ({ status: 404 }),
'Payment.Declined': () => ({ status: 402 }),
});
defineErrors — nothing to rewritecatchTag recoveryNo other error library has this. The linter knows what your functions throw and tells you what you missed.
Flags throw new Error(...) and nudges you toward a typed factory. You fix it in one line.
Analyzes what each function can throw — even across files — and warns when your catch doesn't cover all cases.
Immediately flags every catch block in your codebase that needs updating. You'll never silently miss a new error type.
A pre-configured TypeScript project with faultline installed. Edit the code, run it, experiment with the API.
Open in StackBlitz View examples on GitHubnpm install faultline