Claude
Skills
Sign in
Back

better-result-migrate-v2

Included with Lifetime
$97 forever

Migrate better-result TaggedError usage from the v1 class-based API to the v2 factory-based API. Use when upgrading a codebase that still extends TaggedError directly or calls the old static helpers.

Backend & APIs

What this skill does


# better-result Migrate v2

Upgrade `better-result` error definitions from the v1 `TaggedError` API to the v2 factory-based API.

## When to Use

Use this skill when the user:

- is upgrading `better-result` from v1 to v2
- has classes that `extend TaggedError` directly
- still uses `TaggedError.match`, `TaggedError.matchPartial`, or `TaggedError.isTaggedError`
- needs help rewriting constructor calls to the new object-based form

## Reading Order

| Task                                 | Files to Read                      |
| ------------------------------------ | ---------------------------------- |
| Plan and execute the migration       | This file                          |
| See concrete before/after transforms | `references/migration-patterns.md` |
| Verify current library behavior      | `opensrc/` if present              |

## Quick API Diff

| v1                                    | v2                                                           |
| ------------------------------------- | ------------------------------------------------------------ |
| `class FooError extends TaggedError`  | `class FooError extends TaggedError("FooError")<Props>() {}` |
| `readonly _tag = "FooError" as const` | `_tag` generated by the factory                              |
| `new FooError("123")`                 | `new FooError({ id: "123", message: "..." })`                |
| `TaggedError.match(...)`              | `matchError(...)`                                            |
| `TaggedError.matchPartial(...)`       | `matchErrorPartial(...)`                                     |
| `TaggedError.isTaggedError(...)`      | `isTaggedError(...)` or `TaggedError.is(...)`                |

## Migration Workflow

1. Search for `extends TaggedError` across the codebase.
2. For each class, extract:
   - the `_tag` literal
   - constructor parameters and runtime properties
   - any computed message or validation logic
3. Rewrite the class to `TaggedError("Tag")<Props>()`.
4. If constructor logic exists, keep a custom constructor that accepts an object and calls `super({...})`.
5. Update call sites from positional arguments to object arguments.
6. Replace static helper usage with the new standalone helpers.
7. Update imports.
8. Run tests and search again for old API remnants.

## Transformation Rules

- **Simple class**: remove `_tag`, replace base class, move fields into the generic props object.
- **Computed message**: keep a custom constructor and derive `message` before `super(...)`.
- **Validation logic**: preserve validation inside the custom constructor.
- **Extra runtime fields**: include them in the props object passed to `super(...)`.
- **Usages**: migrate `new FooError(a, b)` to `new FooError({ a, b, message })` or an equivalent derived-message constructor.

Read [references/migration-patterns.md](references/migration-patterns.md) before editing if the target classes are non-trivial.

## Search Checklist

Search for all of these before and after the migration:

- `extends TaggedError`
- `readonly _tag =`
- `TaggedError.match`
- `TaggedError.matchPartial`
- `TaggedError.isTaggedError`
- `new ` call sites for migrated error classes

## Completion Criteria

A migration is complete when:

- no classes directly extend the old v1 `TaggedError` base class
- migrated classes use `TaggedError("...")<...>()`
- call sites use the new constructor shape
- static helper calls are replaced with `matchError`, `matchErrorPartial`, or `isTaggedError`
- imports reflect the new helper functions
- tests pass with the upgraded package version

## Common Pitfalls

- Dropping custom validation logic during the rewrite
- Forgetting to include `message` in the props shape
- Updating class declarations but not constructor call sites
- Replacing `TaggedError.match` but missing `matchPartial` or `isTaggedError`
- Migrating the type but not preserving extra runtime fields like timestamps or codes

## In This Reference

| File                               | Purpose                                                          |
| ---------------------------------- | ---------------------------------------------------------------- |
| `references/migration-patterns.md` | Detailed v1 → v2 before/after examples and import helper changes |

If `opensrc/` exists, use it to confirm the exact v2 API exposed by the installed package.

Related in Backend & APIs