neverthrowでリポジトリ層のエラーをResult型に統一する
TypeScriptプロジェクトでリポジトリ層(DB操作)のエラーハンドリングをtry-catchからneverthrowのResult型に切り替えた。
Before:
// try-catchだと呼び出し側でエラー型が不明
async function createProject(data: NewProject): Promise<Project> {
try {
const result = await db.insert(projects).values(data).returning();
return result[0];
} catch (e) {
throw new Error("Failed to create project");
}
}
After:
import { ok, err, ResultAsync } from "neverthrow";
async function createProject(
data: NewProject
): ResultAsync<Project, RepositoryError> {
return ResultAsync.fromPromise(
db.insert(projects).values(data).returning(),
(e) => new RepositoryError("CREATE_FAILED", e)
).map((rows) => rows[0]);
}
usecase層では .andThen() でチェインし、presentation層で .match() でHTTPレスポンスに変換する。エラーが型で追跡できるので、「このusecaseがどんなエラーを返しうるか」がシグネチャだけで分かる。
テストではリポジトリのモックを集約ファイルに切り出し、ok()/err() で返り値を差し替えると、成功・失敗パスの両方を簡潔にテストできる。