#Result の値を取り出す
Result から実際の値を取り出し、Result から通常の値に戻す必要がある場合、unwrap および unwrapError 関数が役立ちます。
これらの関数は、成功値とエラー値をそれぞれ取り出すための便利な方法を提供します。
#unwrap - 成功値を取り出す
unwrap 関数は Result から成功値を取り出します。
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<42, never> result = import Result Result .const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload) succeed (42);
const const value: 42 value = import Result Result .const unwrap: <Result.Result<42, never>>(result: Result.Result<42, never>) => 42 (+3 overloads) unwrap (const result: Result.Result<42, never> result );
// value: 42#失敗時の動作
Result が Failure でデフォルト値が指定されていない場合、unwrap はエラーを投げます。
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<never, Error> result = import Result Result .const fail: <Error>(error: Error) => Result.Result<never, Error> (+1 overload) fail (new var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error ('Something went wrong'));
const const value: never value = import Result Result .const unwrap: <Result.Result<never, Error>>(result: Result.Result<never, Error>) => never (+3 overloads) unwrap (const result: Result.Result<never, Error> result );
// Throws: Error('Something went wrong')#デフォルト値の指定
デフォルト値を指定することで、エラーが投げられるのを避けられます。
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<never, "error"> result = import Result Result .const fail: <"error">(error: "error") => Result.Result<never, "error"> (+1 overload) fail ('error');
const const value: 0 value = import Result Result .const unwrap: <Result.Result<never, "error">, 0>(result: Result.Result<never, "error">, defaultValue: 0) => 0 (+3 overloads) unwrap (const result: Result.Result<never, "error"> result , 0);
// value: 0 (デフォルト値)import { import Result Result } from '@praha/byethrow';
const const success: Result.Result<42, never> success = import Result Result .const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload) succeed (42);
const const value: 42 | 0 value = import Result Result .const unwrap: <Result.Result<42, never>, 0>(result: Result.Result<42, never>, defaultValue: 0) => 42 | 0 (+3 overloads) unwrap (const success: Result.Result<42, never> success , 0);
// value: 42 (成功値、デフォルトは無視される)#unwrapError - 失敗値を取り出す
unwrapError 関数は逆の動作で失敗値を取り出します。
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<never, "Something went wrong"> result = import Result Result .const fail: <"Something went wrong">(error: "Something went wrong") => Result.Result<never, "Something went wrong"> (+1 overload) fail ('Something went wrong');
const const error: "Something went wrong" error = import Result Result .const unwrapError: <Result.Result<never, "Something went wrong">>(result: Result.Result<never, "Something went wrong">) => "Something went wrong" (+3 overloads) unwrapError (const result: Result.Result<never, "Something went wrong"> result );
// error: 'Something went wrong'#成功時の動作
Result が Success でデフォルト値が指定されていない場合、unwrapError はエラーではなく成功値を投げます。
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<42, never> result = import Result Result .const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload) succeed (42);
const const error: never error = import Result Result .const unwrapError: <Result.Result<42, never>>(result: Result.Result<42, never>) => never (+3 overloads) unwrapError (const result: Result.Result<42, never> result );
// Throws: 42#デフォルトエラーの指定
デフォルト値を指定することで、成功値が投げられるのを避けられます。
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<42, never> result = import Result Result .const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload) succeed (42);
const const error: "No error" error = import Result Result .const unwrapError: <Result.Result<42, never>, "No error">(result: Result.Result<42, never>, defaultValue: "No error") => "No error" (+3 overloads) unwrapError (const result: Result.Result<42, never> result , 'No error');
// error: 'No error' (デフォルト値)import { import Result Result } from '@praha/byethrow';
const const failure: Result.Result<never, "Something went wrong"> failure = import Result Result .const fail: <"Something went wrong">(error: "Something went wrong") => Result.Result<never, "Something went wrong"> (+1 overload) fail ('Something went wrong');
const const error: "Something went wrong" | "No error" error = import Result Result .const unwrapError: <Result.Result<never, "Something went wrong">, "No error">(result: Result.Result<never, "Something went wrong">, defaultValue: "No error") => "Something went wrong" | "No error" (+3 overloads) unwrapError (const failure: Result.Result<never, "Something went wrong"> failure , 'No error');
// error: 'Something went wrong' (失敗値、デフォルトは無視される)#非同期 Result
unwrap と unwrapError は ResultAsync でも動作します。
import { import Result Result } from '@praha/byethrow';
const const asyncResult: Result.ResultAsync<number, never> asyncResult = import Result Result .const succeed: <Promise<number>>(value: Promise<number>) => Result.ResultAsync<number, never> (+1 overload) succeed (var Promise: PromiseConstructorRepresents the completion of an asynchronous operation
Promise .PromiseConstructor.resolve<number>(value: number): Promise<number> (+2 overloads)Creates a new resolved promise for the provided value.
@paramvalue A promise.@returnsA promise whose internal state matches the provided promise. resolve (42));
// Promise を返す
const const value: number value = await import Result Result .const unwrap: <Result.ResultAsync<number, never>>(result: Result.ResultAsync<number, never>) => Promise<number> (+3 overloads) unwrap (const asyncResult: Result.ResultAsync<number, never> asyncResult );
// value: 42デフォルト値を指定する場合。
import { import Result Result } from '@praha/byethrow';
const const asyncResult: Result.ResultAsync<never, string> asyncResult = import Result Result .const fail: <Promise<string>>(error: Promise<string>) => Result.ResultAsync<never, string> (+1 overload) fail (var Promise: PromiseConstructorRepresents the completion of an asynchronous operation
Promise .PromiseConstructor.resolve<string>(value: string): Promise<string> (+2 overloads)Creates a new resolved promise for the provided value.
@paramvalue A promise.@returnsA promise whose internal state matches the provided promise. resolve ('error'));
const const value: 0 value = await import Result Result .const unwrap: <Result.ResultAsync<never, string>, 0>(result: Result.ResultAsync<never, string>, defaultValue: 0) => Promise<0> (+3 overloads) unwrap (const asyncResult: Result.ResultAsync<never, string> asyncResult , 0);
// value: 0#unwrap を使うべき場面
#適切なユースケース
unwrap はアプリケーションの境界(HTTP ハンドラや CLI のエントリーポイントなど)で使用します。
Result の世界を抜けて、外部の世界に通常の値を返す必要がある場所です。
import { import Result Result } from '@praha/byethrow';
const const handleRequest: (req: Request) => Promise<Response> handleRequest = async (req: Request req : Request): interface Promise<T>Represents the completion of an asynchronous operation
Promise <Response> => {
return await import Result Result .const pipe: <Result.ResultAsync<number, "NotFound" | "Unexpected">, Result.ResultAsync<Response, "NotFound" | "Unexpected">, Result.ResultAsync<Response, "Unexpected">, Promise<Response>>(a: Result.ResultAsync<number, "NotFound" | "Unexpected">, ab: (a: Result.ResultAsync<number, "NotFound" | "Unexpected">) => Result.ResultAsync<Response, "NotFound" | "Unexpected">, bc: (b: Result.ResultAsync<Response, "NotFound" | "Unexpected">) => Result.ResultAsync<...>, cd: (c: Result.ResultAsync<...>) => Promise<...>) => Promise<...> (+25 overloads) pipe (
const processRequest: (req: Request) => Result.ResultAsync<number, "NotFound" | "Unexpected"> processRequest (req: Request req ),
import Result Result .const map: <Result.ResultAsync<number, "NotFound" | "Unexpected">, Response>(fn: (a: number) => Response) => (result: Result.ResultAsync<number, "NotFound" | "Unexpected">) => Result.ResultAsync<Response, "NotFound" | "Unexpected"> (+1 overload) map ((result: number result ) => {
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => ResponseThe Response interface of the Fetch API represents the response to a request.
Response (var JSON: JSONAn intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
JSON .JSON.stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string (+1 overload)Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
@paramvalue A JavaScript value, usually an object or array, to be converted.@paramreplacer A function that transforms the results.@paramspace Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.@throws{TypeError} If a circular reference or a BigInt value is found. stringify (result: number result ), { ResponseInit.status?: number | undefined status : 200 });
}),
import Result Result .const orElse: <Result.ResultAsync<Response, "NotFound" | "Unexpected">, Result.Success<Response> | Result.Failure<"Unexpected">>(fn: (a: "NotFound" | "Unexpected") => Result.Success<Response> | Result.Failure<"Unexpected">) => (result: Result.ResultAsync<Response, "NotFound" | "Unexpected">) => Result.ResultAsync<Response, "Unexpected"> (+1 overload) orElse ((error: "NotFound" | "Unexpected" error ) => {
switch (error: "NotFound" | "Unexpected" error ) {
case 'NotFound':
return import Result Result .const succeed: <Response>(value: Response) => Result.Result<Response, never> (+1 overload) succeed (new var Response: new (body?: BodyInit | null, init?: ResponseInit) => ResponseThe Response interface of the Fetch API represents the response to a request.
Response ('Not Found', { ResponseInit.status?: number | undefined status : 404 }));
default:
return import Result Result .const fail: <"Unexpected">(error: "Unexpected") => Result.Result<never, "Unexpected"> (+1 overload) fail (error: "Unexpected" error );
}
}),
// 予期しないエラーはここで投げられ、Sentry や CloudWatch などの
// インフラレベルのエラー監視ツールで検出できます。
import Result Result .const unwrap: <Result.ResultAsync<Response, "Unexpected">>() => (result: Result.ResultAsync<Response, "Unexpected">) => Promise<Response> (+3 overloads) unwrap (),
);
};#unwrap を避けるべき場面
ロジックの途中で unwrap を呼び出すことは避けてください。
そうすると Result の「世界」を早期に抜けてしまい、型安全なエラー処理の利点が失われます。
代わりに、値を Result でラップしたまま保持し、map、flatMap、orElse などの関数を組み合わせて変換してください。
import { import Result Result } from '@praha/byethrow';
// ❌ これはやめましょう
const const bad: number bad = import Result Result .const unwrap: <Result.Result<42, never>>(result: Result.Result<42, never>) => 42 (+3 overloads) unwrap (import Result Result .const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload) succeed (42)) * 2;
// ✅ 代わりにこうしましょう
const const good: Result.Result<number, never> good = import Result Result .const pipe: <Result.Result<42, never>, Result.Result<number, never>>(a: Result.Result<42, never>, ab: (a: Result.Result<42, never>) => Result.Result<number, never>) => Result.Result<number, never> (+25 overloads) pipe (
import Result Result .const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload) succeed (42),
import Result Result .const map: <Result.Result<42, never>, number>(fn: (a: 42) => number) => (result: Result.Result<42, never>) => Result.Result<number, never> (+1 overload) map ((x: 42 x ) => x: 42 x * 2),
);#リファレンス
| 関数 | 目的 |
|---|---|
| unwrap(result) | Result から成功値を取り出す。失敗時はエラーを投げるまたはデフォルト値を返す |
| unwrapError(result) | Result からエラー値を取り出す。成功時は値を投げるまたはデフォルト値を返す |
