Skip to content

feat(client): add runtime isError guards to all public ...Error unions#7

Merged
cesarenaldi merged 2 commits into
mainfrom
claude/frosty-ramanujan-e9b3ef
Apr 23, 2026
Merged

feat(client): add runtime isError guards to all public ...Error unions#7
cesarenaldi merged 2 commits into
mainfrom
claude/frosty-ramanujan-e9b3ef

Conversation

@cesarenaldi
Copy link
Copy Markdown
Collaborator

@cesarenaldi cesarenaldi commented Apr 22, 2026

Summary

  • Adds a makeErrorGuard(...classes) helper in errors.ts that takes concrete error constructors and returns { isError(error: unknown): error is Union } via instanceof checks — the union type is inferred from the constructor tuple
  • Adds a same-named export const FooError = makeErrorGuard(...) alongside every export type FooError union across 27 source files (all action files, abis.ts, types.ts, workflow.ts)
  • Re-exports ./actions from the root index.ts so guards are accessible from @polymarket/client without a sub-path import
  • Adds errors.test.ts with 3 tests covering positive hits, non-SDK rejection, and type-narrowing

Consumer ergonomics

try {
  await client.listMarkets();
} catch (error) {
  if (ListMarketsError.isError(error)) {
    switch (error.name) {
      case 'RateLimitError':
        // retry...
        break;
      case 'RequestRejectedError':
        // handle 4xx...
        break;
    }
  }
}

Both the existing import type { ListMarketsError } (union type) and the new import { ListMarketsError } (guard object) are exported under the same name, using TypeScript's separate type/value namespaces — no breaking change.

Design notes

  • Guard uses instanceof, not error.name string matching, so subclasses are handled correctly
  • For alias unions (PrepareMarketOrderPostingError = PrepareMarketOrderError), the const is a direct reference to the parent guard — no duplication
  • For composed unions in gasless.ts where the inner type is module-private (ExecuteGaslessError), the classes are flattened at the call site
  • WaitForTransactionError in types.ts imports classes directly from ./errors to avoid a circular value dependency through ./actions

Test plan

  • pnpm lint — clean
  • pnpm typecheck — clean
  • pnpm vitest run --project client packages/client/src/errors.test.ts — 3/3 pass

🤖 Generated with Claude Code


Note

Low Risk
Low risk: changes are additive (new makeErrorGuard helper and exported guard values) and don’t alter request/transaction behavior, but they do expand the public API surface via additional exports.

Overview
Adds a generic makeErrorGuard(...classes) helper and, alongside each existing ...Error type union, exports a same-named const with an isError(error) runtime type guard inferred from the provided error constructors.

Updates decorators to re-export these error guards/unions per action group, adjusts root exports (including AuthenticateWithError/CompleteWithError) so consumers can import guards from the package entrypoint, and adds a small vitest suite validating guard behavior and TypeScript narrowing.

Reviewed by Cursor Bugbot for commit 6af2b1f. Bugbot is set up for automated code reviews on this repo. Configure here.

Each exported `...Error` union now has a same-named runtime constant
with an `isError(error: unknown): error is ...Error` type guard built
from `instanceof` checks, enabling exhaustive switch-on-name patterns:

  if (ListMarketsError.isError(error)) {
    switch (error.name) { ... }
  }

- Add `makeErrorGuard(...classes)` helper in `errors.ts`; infers the
  guard union type from the constructor tuple — single source of truth
- Add `export const FooError = makeErrorGuard(A, B, C)` alongside
  every `export type FooError` across 27 source files (actions, abis,
  types, workflow)
- Re-export `./actions` from the root entry point so guards are
  accessible from `@polymarket/client` without a sub-path import
- Add `errors.test.ts` covering positive hits, non-SDK rejection, and
  type-narrowing behaviour

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ctions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cesarenaldi cesarenaldi merged commit 58006fb into main Apr 23, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant