Result/Eitherスタイルの型
Result/Eitherのユニオンで成功と失敗を明示的にモデル化し、ヘルパー(map/flatMap/mapError)を追加します。あらゆる箇所をtry/catchで囲まず、処理の流れを予測可能に保ちます。
「Result/Eitherスタイルの型」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン1/2です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全2レッスンが含まれています。
導入
目標:失敗を見える化します。判別可能なユニオンで結果をモデル化し、ヘルパーで組み合わせ、境界で例外を変換します。
- Result型
- map/flatMap/mapError
- HTTPとの統合
Result の基本
小さなResultユーティリティを作成します。ok/errコンストラクターに加えて、組み合わせに使うmap、flatMap、mapErrorを用意します。
export type Ok<T> = { ok: true; value: T }
export type Err<E> = { ok: false; error: E }
export type Result<T, E> = Ok<T> | Err<E>
export const ok = <T>(value: T): Ok<T> => ({ ok: true, value })
export const err = <E>(error: E): Err<E> => ({ ok: false, error })
export function map<T, E, U>(r: Result<T, E>, f: (t: T) => U): Result<U, E> {
return r.ok ? ok(f(r.value)) : r
}
export function flatMap<T, E, U>(r: Result<T, E>, f: (t: T) => Result<U, E>): Result<U, E> {
return r.ok ? f(r.value) : r
}
export function mapError<T, E, F>(r: Result<T, E>, g: (e: E) => F): Result<T, F> {
return r.ok ? r : err(g(r.error))
}ドメインエラー
ドメインエラーをtag付きの判別可能なユニオンとしてモデル化します。各分岐に正確なデータを持たせることで、適切なメッセージを作成できます。
export type CreateUserError =
| { tag: "InvalidEmail"; detail?: string }
| { tag: "Duplicate"; email: string }
export function validateEmail(email: string): Result<string, CreateUserError> {
const okEmail = /.+@.+/.test(email)
return okEmail ? ok(email.toLowerCase()) : err({ tag: "InvalidEmail", detail: "bad format" })
}
const existing = new Set(["ada@example.com"]) // pretend DB
export function saveUser(email: string): Result<{ id: string }, CreateUserError> {
if (existing.has(email)) return err({ tag: "Duplicate", email })
return ok({ id: Math.random().toString(36).slice(2) })
}フローの組み合わせ
flatMapで検証を組み合わせます。neverチェック付きのswitchを使用して、コンパイル時にすべてのケースを処理していることを保証します。
export function createUser(flowEmail: string) {
return flatMap(validateEmail(flowEmail), email => saveUser(email))
}
// Use
const r = createUser("Ada@example.com")
if (r.ok) {
console.log("id:", r.value.id)
} else {
switch (r.error.tag) {
case "InvalidEmail": console.error("invalid email:", r.error.detail); break
case "Duplicate": console.error("already used:", r.error.email); break
default: ((x: never) => x)(r.error) // exhaustiveness
}
}例外 → Result
I/O境界で例外をラップし、Resultに変換します。呼び出し側では、処理すべきエラーパスを1つに保てます。
export async function fromPromise<T>(p: Promise<T>): Promise<Result<T, { tag: "Exception"; message: string }>> {
try { return ok(await p) }
catch (e) { return err({ tag: "Exception", message: e instanceof Error ? e.message : String(e) }) }
}
// Example: wrap a fetch
export async function fetchJson<T>(url: string): Promise<Result<T, { tag: "Exception"; message: string }>> {
return fromPromise(fetch(url).then(r => r.json() as T))
}HTTPマッピングのヒント
HTTPとの統合:ドメインエラーを400/409に、I/O例外を502/503にマッピングします。マッパー関数は小さく保ち、コントローラーを明確で予測可能な状態にします。
Result の利点チェック
クイックチェック:なぜ判別可能なResultユニオンを優先するのですか?
まとめ
まとめ:小さなResult型を定義し、map/flatMapで組み合わせ、ドメインエラーをユニオンとしてモデル化し、境界で例外を変換します。
よくある質問
「Result/Eitherスタイルの型」レッスンは無料ですか?
はい。「Result/Eitherスタイルの型」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全2レッスンが含まれています。
「Result/Eitherスタイルの型」で何を学びますか?
Result/Eitherのユニオンで成功と失敗を明示的にモデル化し、ヘルパー(map/flatMap/mapError)を追加します。あらゆる箇所をtry/catchで囲まず、処理の流れを予測可能に保ちます。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
TypeScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/2です。
「Result/Eitherスタイルの型」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このTypeScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Result/Eitherスタイルの型
- 判別可能ユニオンによる網羅的なエラー処理