Skip to content

[BUG] is() should return TypeScript type predicate for narrowing #35

Description

@martyy-code

Bug Description

is(err, SomeError) returns a plain boolean, not a TypeScript type predicate. Consumers cannot narrow the error type after the check:

if(is(err,NotFoundError)){// err is still typed as ErrorInstance<unknown> — no narrowingconsole.log(err.fields.slug)// TS error}

This forces consumers to cast (err as NotFoundError) or duplicate the narrowing logic. With three try/catch blocks per command and ~7 error types, this churn adds up.

Steps to Reproduce

  1. npm install @deessejs/errors
  2. Create repro.ts:
import{error,is}from"@deessejs/errors"constNotFoundError=error({name: "NotFoundError"})constOtherError=error({name: "OtherError"})consterr: unknown=NotFoundError()if(is(err,NotFoundError)){// Expected: err is now inferred as NotFoundError instance// Actual: err is still unknownconsole.log(err)}
  1. Run tsc --noEmit and try to access any field on err inside the if branch.

Expected Behavior

is() should return err is ErrorInstance<TError, ...> (a type predicate), so TypeScript narrows automatically.

Actual Behavior

No narrowing. The if branch treats err as unknown unless the consumer casts.

Environment

  • Node.js: 22.x
  • pnpm: 11.0.0
  • OS: Linux
  • @deessejs/errors: 1.1.1

Consumer

deessejs/deessejs monorepo, apps/cli workspace. Would unblock the planned migration of commands/info.ts, commands/list.ts, commands/init.ts to use is(err, CliError) instead of err.name === "CliError".

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingeffort: xsA few minutesp1: highRequired for next releasestatus: triageTech Lead has not seen it yettype: bugBug / defect fix

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions