Skip to content

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

Closed as not planned

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 narrowing
  console.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"

const NotFoundError = error({ name: "NotFoundError" })
const OtherError = error({ name: "OtherError" })

const err: unknown = NotFoundError()

if (is(err, NotFoundError)) {
  // Expected: err is now inferred as NotFoundError instance
  // Actual: err is still unknown
  console.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".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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