better-result-adopt
既存のTypeScriptコードベースにbetter-resultを導入します。`try/catch`やPromiseのrejection処理、nullセンチネル、ドメイン例外のthrowを型付きResultワークフローへ置き換えたい場合に使用してください。
description の原文を見る
Adopt better-result in an existing TypeScript codebase. Use when replacing try/catch, Promise rejection handling, null sentinels, or thrown domain exceptions with typed Result workflows.
SKILL.md 本文
better-result 採用
既存のコードベースに better-result を段階的に採用し、すべてを一度に書き直すことなく進めます。
使用時期
ユーザーが以下を望む場合、このスキルを使用します:
- try/catch から
Result.tryまたはResult.tryPromiseへ移行 - null を返す値を型付き
Result<T, E>で置き換え - domain 固有の
TaggedError型を定義 - ネストされたエラー処理を
andThenチェーンまたはResult.genにリファクタリング - サービスまたはモジュール全体でエラー処理を標準化
読む順序
| タスク | 読むべきファイル |
|---|---|
| モジュールで better-result を採用 | このファイル |
| エラー型を定義または確認 | references/tagged-errors.md |
| ライブラリ実装の詳細を検査 | opensrc/ (存在する場合) |
前提条件
コード編集前に以下を確認してください:
- ターゲットプロジェクトに
better-resultがインストール済みであることを確認。 opensrc/ディレクトリがあるかチェック。ある場合は、そこのパッケージソースを読んで現在のパターンを確認。- まず移行スコープを特定:1 ファイル、1 モジュール、または 1 境界レイヤー。
移行戦略
1. 境界から始める
I/O 境界と例外が多いコードから始めます:
- HTTP クライアント
- データベースアクセス
- ファイルシステム操作
- パースと検証
- フレームワークアダプター
コードベース全体を一度に変換しないこと。
2. 既存の失敗を分類
| カテゴリ | 例 | ターゲット形状 |
|---|---|---|
| Domain エラー | 見つからない、検証、認証 | TaggedError + Result.err |
| インフラストラクチャ | ネットワーク、DB、ファイル I/O | Result.tryPromise + mapped error |
| プログラマの欠陥 | 不正な仮定、null 参照 | throw のまま;欠陥は Result コールバック内で Panic に |
3. この順序で移行
- エラー型を定義。
Result.try/Result.tryPromiseで throw 境界をラップ。- null または boolean sentinel リターンを
Resultで置き換え。 - コールサイトをリファクタリングして
Result値を伝播。 - ネストされた分岐を
andThen、mapError、またはResult.genに折りたたむ。
コア変換
Try/catch → Result.try
function parseConfig(json: string): Result<Config, ParseError> {
return Result.try({
try: () => JSON.parse(json) as Config,
catch: (cause) => new ParseError({ cause, message: `Parse failed: ${cause}` }),
});
}
Async throws → Result.tryPromise
async function fetchUser(id: string): Promise<Result<User, ApiError | UnhandledException>> {
return Result.tryPromise({
try: async () => {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new ApiError({ status: res.status, message: `API ${res.status}` });
return res.json() as Promise<User>;
},
catch: (cause) => (cause instanceof ApiError ? cause : new UnhandledException({ cause })),
});
}
Null sentinel → Result
function findUser(id: string): Result<User, NotFoundError> {
const user = users.find((candidate) => candidate.id === id);
return user
? Result.ok(user)
: Result.err(new NotFoundError({ id, message: `User ${id} not found` }));
}
ネストされたフロー → Result.gen
async function processOrder(orderId: string): Promise<Result<OrderResult, OrderError>> {
return Result.gen(async function* () {
const order = yield* Result.await(fetchOrder(orderId));
const validated = yield* validateOrder(order);
const result = yield* Result.await(submitOrder(validated));
return Result.ok(result);
});
}
実行ワークフロー
- ターゲットモジュールを監査して、
try、catch、.catch(...)、throw、null、undefined、status フラグエラー処理を探す。 - 制御フローを変更する前に、
TaggedErrorクラスを定義または更新。 - 境界関数を最初に変換し、シグネチャを
Result<T, E>またはPromise<Result<T, E>>に変更。 - 即座の呼び出し元を更新して、新しい
Resultを処理または伝播。 - 複数の Result 返却ステップが構成される場所では、
Result.genまたはandThenを使用。 - エラーコンテキストを保持して、
cause、ID、メッセージ、その他の構造化フィールドを保存。 - テストを実行し、成功パスと少なくとも 1 つの代表的なエラーパスに対応するテストカバレッジを追加。
完了基準
移行は以下を満たす場合に完了です:
- ターゲット関数が、期待される domain の失敗に対して try/catch に依存しない
- null または sentinel エラーリターンが明示的な
Result値で置き換えられている - domain の失敗が型付き
TaggedErrorクラスを使用している - 呼び出し元が
Resultを伝播するか、明示的にアンラップまたはマッチしている - テストが少なくとも 1 つの成功パスと 1 つの代表的なエラーパスをカバーしている
よくある落とし穴
- 境界から始める代わりに、すべてをオーバーラップ
- エラーをマップするときに元の失敗コンテキストを失う
- 同じフロー内で throw ベースと
Resultベースの API を混ぜる - 根本的な欠陥を修正せず
Panicをキャッチする
このリファレンス内
| ファイル | 目的 |
|---|---|
references/tagged-errors.md | TaggedError パターン、マッチング、型ガード、例 |
opensrc/ が存在する場合、実装の詳細と現在の API 動作の信頼できるソースとして扱ってください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- dmmulroy
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/dmmulroy/better-result / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。