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

失敗時の動作

ResultFailure でデフォルト値が指定されていない場合、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'

成功時の動作

ResultSuccess でデフォルト値が指定されていない場合、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

unwrapunwrapErrorResultAsync でも動作します。

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: PromiseConstructor

Represents 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: PromiseConstructor

Represents 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) => Response

The Response interface of the Fetch API represents the response to a request.

MDN Reference

Response
(
var JSON: JSON

An 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) => Response

The Response interface of the Fetch API represents the response to a request.

MDN Reference

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 でラップしたまま保持し、mapflatMaporElse などの関数を組み合わせて変換してください。

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 からエラー値を取り出す。成功時は値を投げるまたはデフォルト値を返す