neverthrow-return-types について
neverthrow-return-typesは、TypeScript開発で互換性のある関数やメソッドにneverthrowのResultまたはResultAsyncを使うためのスキルです。先に周囲の契約を確認し、別の戻り値が必要な境界では内部にneverthrowを保ちます。
主な機能
- 01関数やメソッドの戻り値契約を確認
- 02同期処理にResultを使用
- 03非同期処理にResultAsyncを使用
- 04非互換な境界の内部でneverthrowを使用
- 05エラー型・インポート・変更を検証
活用シーン
- 01サービスやドメインAPIの戻り値型を統一
- 02クラスやオブジェクトのメソッドのエラー返却を変更
- 03フレームワークのコールバック境界で内部Resultを変換
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ code-sherpas/ agent-skills --skill neverthrow-return-typesインストール後、Claude Code で/neverthrow-return-typesを入力して読み込まれたか確認します。
詳細
Neverthrow の戻り値型
目標
互換性のあるすべての関数とメソッドを、neverthrow の戻り値型でモデル化します。
このスキルが規定するのは戻り値のシグネチャのみです。スローされた例外や拒否されたプロミスの捕捉方法も変更するタスクでは、このスキルと併せて neverthrow-wrap-exceptions を使用してください。
このルールは、以下に適用します。
- スタンドアロン関数
- エクスポートされたモジュール関数
- クラスメソッド
- オブジェクトリテラルのメソッド
- ファクトリーが返すメソッド
- サービス、リポジトリ、ドメインの API
ネストされていることを例外として扱わないでください。クラスやオブジェクト内のメソッドにも、トップレベルの関数と同じルールが適用されます。
許可される唯一の例外は、周囲のテクノロジー、ライブラリ、またはフレームワークによって強制される互換性のない境界です。
互換性を最初に確認する
-
編集する前に、関数またはメソッドの実際の契約を特定します。
- 実装するインターフェース、オーバーライドするメンバー、フレームワークのコールバック型、デコレーター、ライフサイクルフック、ルートハンドラーのシグネチャ、コンポーネントのシグネチャ、公開 SDK の契約を確認します。
- 契約がすでに
ResultまたはResultAsyncを要求している場合は、そのまま維持します。 - 契約が別の形式を要求している場合、その境界には互換性がありません。
-
ローカルのテクノロジーが
neverthrowの戻り値を明示的にサポートしていない限り、以下を一般的な互換性のない境界として扱います。- 要素またはノードを返す必要がある UI のレンダー関数。
Response、フレームワークの返信オブジェクト、void、またはそれらの値のPromiseを返す必要があるフレームワークのルートハンドラー、ミドルウェア、ローダー、アクション、コントローラー、リゾルバー。- イベントリスナー、テストコールバック、コンストラクター、ゲッター、セッター、および実行時のシグネチャが固定されているその他の API。
- 宣言された戻り値型を
ResultまたはResultAsyncに拡張できないインターフェースの実装やオーバーライドされたメソッド。
-
互換性がない場合は、境界の内側で
neverthrowを使用します。- ビジネスロジックを、
ResultまたはResultAsyncを返す内部ヘルパー関数やメソッドに移します。 - 最終的な
OkまたはErrをフレームワーク本来の戻り値に変換するのは、最外部の境界に限ります。 - 境界自体が
neverthrowを返せないというだけで、null、センチネル値、フレームワーク固有の近道など、その場しのぎの失敗形式に切り替えないでください。
- ビジネスロジックを、
-
対象プロジェクトに
neverthrowの依存関係がない場合、タスクで依存関係の変更が許可されている場合に限り、依存関係を追加します。- 依存関係の変更が対象範囲外の場合は、現時点ではこのポリシーを完全には適用できないことを明記します。
戻り値型を選択する
- 同期処理には
Result<T, E>を使用します。 - 非同期処理には
ResultAsync<T, E>を使用します。 Eには明示的なドメインエラー型を優先します。- ローカルのスタイルに合わせて、判別可能なユニオン、タグ付きオブジェクト、または安定したエラークラスを使用します。
- コードベースで標準化されている場合を除き、
unknown、any、曖昧な文字列エラーは避けます。
- 成功値と失敗値を明示的に構築するには、
ok(...)、err(...)、okAsync(...)、errAsync(...)を使用します。
実装ルール
-
公開契約を
ResultAsync<T, E>にすべき関数やメソッドには、asyncを付けないでください。- 呼び出し側が
.map、.mapErr、.andThen、.orElseで合成できるよう、ResultAsyncを直接返します。 - フレームワークの境界でネイティブの
Promiseが明示的に必要な場合を除き、Promise<Result<T, E>>は避けます。
- 呼び出し側が
-
モジュールを変更する場合、そのスコープ内で編集した互換性のあるすべての関数とメソッドを更新します。
- 要求された変更の対象となる、近接する互換性のあるクラスメソッドやオブジェクトメソッドを非
neverthrowシグネチャのまま残し、トップレベル関数だけを変換しないでください。
- 要求された変更の対象となる、近接する互換性のあるクラスメソッドやオブジェクトメソッドを非
境界のパターン
外部 API が neverthrow を返せない場合は、次のパターンを使用します。
function createUser(
input: CreateUserInput,
): ResultAsync<User, CreateUserError> {
return validateInput(input).asyncAndThen(insertUser)
}
export async function post(request: Request): Promise<Response> {
const result = await createUser(await request.json())
return result.match(
(user) => Response.json(user, { status: 201 }),
(error) => toErrorResponse(error),
)
}
完了前の検証
- 編集した互換性のある関数またはメソッドがすべて、
ResultまたはResultAsyncを返すようになったことを確認します。 - 互換性のない境界が内部の
neverthrowの結果を利用して変換され、回避されていないことを確認します。 - インポート元が
neverthrowであり、実際の使用方法と一致していることを確認します。 - エラー型が明示的で、呼び出し元にとって十分に安定していることを確認します。
- 安全で作業範囲内であれば、テスト、リンティング、型チェックなど、スタックに応じた通常のローカル検証を実行します。
結果の報告
タスクを完了する際は、以下を報告します。
ResultまたはResultAsyncを返すようになった関数またはメソッド。- 非
neverthrowのまま残した境界と、互換性がなかった理由。 Err値の型指定とマッピング方法。