Install any skill in seconds. Free to start, no credit card required.
Get Started Free →saffron-health/errore
errore is Go-style error handling for TypeScript: return errors instead of throwing them. Instead of Go's two-value tuple (val, err), functions return a single Error | T union. Instead of checking err != nil, you check instanceof Error. TypeScript narrows the type automatically — forget to check and your code won't compile. No wrapper types, no Result monads, just unions and instanceof. The errore npm package provides helper utilities (createTaggedError, tryAsync, matchError, findCause, partitio
Passed 21 of 22 test cases with the skill, and 8 of 22 without it.
and 18 more in the full report
13 fixed8 passed either way1 still failing0 broke
Tokens, turns and time describe resource use, not a dollar price.
One of 13 test cases the skill fixed. Same model, same prompt, with and without the skill.
Write a TypeScript function that fetches a resource, returns early if an error occurred, and calls `.text()` on the response without creating a redundant narrowed variable alias.
| Checked | Without skill | With skill |
|---|---|---|
| Invokes methods directly on the response variable after the instanceof Error check. | Missed | Passed |
The instructions your model reads when the skill loads.
Go-style error handling for TypeScript. Functions return errors instead of throwing them — but instead of Go's two-value tuple (val, err), you return a single Error | T union. Instead of checking err != nil, you check instanceof Error. TypeScript narrows the type automatically. No wrapper types, no Result monads, just unions and instanceof.
const user = await getUser(id)
if (user instanceof Error) return user // early return, like Go
console.log(user.name) // TypeScript knows: User
Always import * as errore from 'errore' — namespace import, never destructure
Never throw for expected failures — return errors as values
Never return unknown | Error — the union collapses to unknown, breaks narrowing. Common trap: res.json() returns unknown, so return await res.json() makes the return type MyError | unknown → unknown. Fix: cast with as → return (await res.json()) as User
Avoid try-catch for control flow — use .catch() for async boundaries, errore.try for sync boundaries
Use createTaggedError for domain errors — gives you _tag, typed properties, $variable interpolation, cause, findCause, toJSON, and fingerprinting
Let TypeScript infer return types — only add explicit annotations when they improve readability (complex unions, public APIs) or when inference produces a wider type than intended
Use cause to wrap errors — new MyError({ ..., cause: originalError })
Use | null for optional values, not | undefined — three-way narrowing: instanceof Error, === null, then value
Use const + expressions, never let + try-catch — ternaries, IIFEs, instanceof Error
Always handle errors inside if branches with early exits, keep the happy path at root — like Go's if err != nil { return err }, check the error, exit (return/continue/break), and continue the success path at the top indentation level. This makes the happy path readable top-to-bottom with minimal nesting
Always include Error handler in matchError — required fallback for plain Error instances
Use .catch() for async boundaries, errore.try for sync boundaries — only at the lowest call stack level where you interact with uncontrolled dependencies (third-party libs, JSON.parse, fetch, file I/O). Your own code should return errors as values, not throw.
Always wrap .catch() in a tagged domain error — .catch((e) => new MyError({ cause: e })). The .catch() callback receives any, but wrapping in a typed error gives the union a concrete type. Never use .catch((e) => e as Error) — always wrap.
Always pass cause in .catch() callbacks — .catch((e) => new MyError({ cause: e })), never .catch(() => new MyError()). Without cause, the original error is lost and isAbortError can't walk the chain to detect aborts. The cause preserves the full error chain for debugging and abort detection.
Always prefer errore.try over errore.tryFn — they are the same function, but errore.try is the canonical name
Use errore.isAbortError to detect abort errors — never check error.name === 'AbortError' manually, because tagged abort errors have their tag as .name
Custom abort errors MUST extend errore.AbortError — so isAbortError detects them in the cause chain even when wrapped by .catch()
Keep abort checks flat — check isAbortError(result) first as its own early return, then result instanceof Error as a separate early return. Never nest isAbortError inside instanceof Error:
const result = await fetchData({ signal }).catch(
(e) => new FetchError({ cause: e }),
)
if (errore.isAbortError(result)) return 'Request timed out'
if (result instanceof Error) return `Failed: ${result.message}`
Don't reassign after error early returns — TypeScript narrows the original variable automatically after instanceof Error checks return. A const narrowed = result alias is redundant:
test cases passed, vs 8 / 22 without
More skills from the same source and nearby in the registry, with their headline benchmark lift.