#オブジェクトを構築する
各フィールドが成功した計算に依存する複雑なオブジェクトを構築する場合、do/bind パターンが非常に便利です。
これにより、成功した結果を蓄積しながらオブジェクトを構築できます。
#do とは?
do は空のオブジェクトを持つ Success という特別な Result を作成します。
import { import Result Result } from '@praha/byethrow';
const const start: Result.Result<{}, never> start = import Result Result .function do(): import("/home/runner/work/byethrow/byethrow/packages/byethrow/dist/esm/result").Result<{}, never>
export do
Alias for succeed({}). Commonly used as a neutral base value in functional chains or monadic pipelines.
@function@exampleimport { Result } from '@praha/byethrow';
const result = Result.do();
// Result.Result<{}, never>
@categoryCreators do ();
// { type: 'Success', value: {} }#bind とは?
bind は蓄積されたオブジェクトに新しいフィールドを追加し、以下の処理を行います。
- 現在の蓄積されたオブジェクトを受け取る
Resultを返す計算を実行する- 成功した場合、指定されたキーでオブジェクトに結果をマージする
- 失敗した場合、ショートサーキットして失敗を返す
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<{
name: "Alice";
age: 30;
}, never>
result = import Result Result .const pipe: <Result.Result<{}, never>, Result.Result<{
name: "Alice";
}, never>, Result.Result<{
name: "Alice";
age: 30;
}, never>>(a: Result.Result<{}, never>, ab: (a: Result.Result<{}, never>) => Result.Result<{
name: "Alice";
}, never>, bc: (b: Result.Result<{
name: "Alice";
}, never>) => Result.Result<{
name: "Alice";
age: 30;
}, never>) => Result.Result<{
name: "Alice";
age: 30;
}, never> (+25 overloads)
pipe (
import Result Result .function do(): import("/home/runner/work/byethrow/byethrow/packages/byethrow/dist/esm/result").Result<{}, never>
export do
Alias for succeed({}). Commonly used as a neutral base value in functional chains or monadic pipelines.
@function@exampleimport { Result } from '@praha/byethrow';
const result = Result.do();
// Result.Result<{}, never>
@categoryCreators do (),
import Result Result .const bind: <"name", Result.Result<{}, never>, Result.Result<"Alice", never>>(name: "name", fn: (a: {}) => Result.Result<"Alice", never>) => (result: Result.Result<{}, never>) => Result.Result<{
name: "Alice";
}, never> (+1 overload)
bind ('name', () => import Result Result .const succeed: <"Alice">(value: "Alice") => Result.Result<"Alice", never> (+1 overload) succeed ('Alice')),
import Result Result .const bind: <"age", Result.Result<{
name: "Alice";
}, never>, Result.Result<30, never>>(name: "age", fn: (a: {
name: "Alice";
}) => Result.Result<30, never>) => (result: Result.Result<{
name: "Alice";
}, never>) => Result.Result<{
name: "Alice";
age: 30;
}, never> (+1 overload)
bind ('age', () => import Result Result .const succeed: <30>(value: 30) => Result.Result<30, never> (+1 overload) succeed (30)),
);
// { type: 'Success', value: { name: 'Alice', age: 30 } }#以前の値の使用
bind の強力な点は、各ステップで以前の値にアクセスできることです。
import { import Result Result } from '@praha/byethrow';
const const result: Result.ResultAsync<{
user: {
id: string;
profileId: string;
};
profile: {
bio: string;
};
}, "UserNotFound" | "ProfileNotFound">
result = import Result Result .const pipe: <Result.Result<{}, never>, Result.ResultAsync<{
user: {
id: string;
profileId: string;
};
}, "UserNotFound">, Result.ResultAsync<{
user: {
id: string;
profileId: string;
};
profile: {
bio: string;
};
}, "UserNotFound" | "ProfileNotFound">>(a: Result.Result<{}, never>, ab: (a: Result.Result<{}, never>) => Result.ResultAsync<{
user: {
id: string;
profileId: string;
};
}, "UserNotFound">, bc: (b: Result.ResultAsync<{
user: {
id: string;
profileId: string;
};
}, "UserNotFound">) => Result.ResultAsync<{
user: {
id: string;
profileId: string;
};
profile: {
bio: string;
};
}, "UserNotFound" | "ProfileNotFound">) => Result.ResultAsync<...> (+25 overloads)
pipe (
import Result Result .function do(): import("/home/runner/work/byethrow/byethrow/packages/byethrow/dist/esm/result").Result<{}, never>
export do
Alias for succeed({}). Commonly used as a neutral base value in functional chains or monadic pipelines.
@function@exampleimport { Result } from '@praha/byethrow';
const result = Result.do();
// Result.Result<{}, never>
@categoryCreators do (),
import Result Result .const bind: <"user", Result.Result<{}, never>, Result.ResultAsync<{
id: string;
profileId: string;
}, "UserNotFound">>(name: "user", fn: (a: {}) => Result.ResultAsync<{
id: string;
profileId: string;
}, "UserNotFound">) => (result: Result.Result<{}, never>) => Result.ResultAsync<{
user: {
id: string;
profileId: string;
};
}, "UserNotFound"> (+1 overload)
bind ('user', () => const fetchUser: (userId: string) => Result.ResultAsync<{
id: string;
profileId: string;
}, "UserNotFound">
fetchUser ('user-123')),
import Result Result .const bind: <"profile", Result.ResultAsync<{
user: {
id: string;
profileId: string;
};
}, "UserNotFound">, Result.ResultAsync<{
bio: string;
}, "ProfileNotFound">>(name: "profile", fn: (a: {
user: {
id: string;
profileId: string;
};
}) => Result.ResultAsync<{
bio: string;
}, "ProfileNotFound">) => (result: Result.ResultAsync<{
user: {
id: string;
profileId: string;
};
}, "UserNotFound">) => Result.ResultAsync<{
user: {
id: string;
profileId: string;
};
profile: {
bio: string;
};
}, "UserNotFound" | "ProfileNotFound"> (+1 overload)
bind ('profile', ({ user: {
id: string;
profileId: string;
}
user }) => const fetchProfile: (profileId: string) => Result.ResultAsync<{
bio: string;
}, "ProfileNotFound">
fetchProfile (user: {
id: string;
profileId: string;
}
user .profileId: string profileId )), // userを使用!
);#失敗時のショートサーキット
いずれかの bind が失敗すると、後続の bind はスキップされます。
import { import Result Result } from '@praha/byethrow';
const const result: Result.Result<{
a: 1;
b: never;
c: 3;
d: 4;
}, "Error!">
result = import Result Result .const pipe: <Result.Result<{}, never>, Result.Result<{
a: 1;
}, never>, Result.Result<{
a: 1;
b: never;
}, "Error!">, Result.Result<{
a: 1;
b: never;
c: 3;
}, "Error!">, Result.Result<{
a: 1;
b: never;
c: 3;
d: 4;
}, "Error!">>(a: Result.Result<{}, never>, ab: (a: Result.Result<{}, never>) => Result.Result<{
a: 1;
}, never>, bc: (b: Result.Result<{
a: 1;
}, never>) => Result.Result<{
a: 1;
b: never;
}, "Error!">, cd: (c: Result.Result<{
a: 1;
b: never;
}, "Error!">) => Result.Result<{
a: 1;
b: never;
c: 3;
}, "Error!">, de: (d: Result.Result<...>) => Result.Result<...>) => Result.Result<...> (+25 overloads)
pipe (
import Result Result .function do(): import("/home/runner/work/byethrow/byethrow/packages/byethrow/dist/esm/result").Result<{}, never>
export do
Alias for succeed({}). Commonly used as a neutral base value in functional chains or monadic pipelines.
@function@exampleimport { Result } from '@praha/byethrow';
const result = Result.do();
// Result.Result<{}, never>
@categoryCreators do (),
import Result Result .const bind: <"a", Result.Result<{}, never>, Result.Result<1, never>>(name: "a", fn: (a: {}) => Result.Result<1, never>) => (result: Result.Result<{}, never>) => Result.Result<{
a: 1;
}, never> (+1 overload)
bind ('a', () => import Result Result .const succeed: <1>(value: 1) => Result.Result<1, never> (+1 overload) succeed (1)),
import Result Result .const bind: <"b", Result.Result<{
a: 1;
}, never>, Result.Result<never, "Error!">>(name: "b", fn: (a: {
a: 1;
}) => Result.Result<never, "Error!">) => (result: Result.Result<{
a: 1;
}, never>) => Result.Result<{
a: 1;
b: never;
}, "Error!"> (+1 overload)
bind ('b', () => import Result Result .const fail: <"Error!">(error: "Error!") => Result.Result<never, "Error!"> (+1 overload) fail ('Error!')), // ここで失敗
import Result Result .const bind: <"c", Result.Result<{
a: 1;
b: never;
}, "Error!">, Result.Result<3, never>>(name: "c", fn: (a: {
a: 1;
b: never;
}) => Result.Result<3, never>) => (result: Result.Result<{
a: 1;
b: never;
}, "Error!">) => Result.Result<{
a: 1;
b: never;
c: 3;
}, "Error!"> (+1 overload)
bind ('c', () => import Result Result .const succeed: <3>(value: 3) => Result.Result<3, never> (+1 overload) succeed (3)), // スキップ
import Result Result .const bind: <"d", Result.Result<{
a: 1;
b: never;
c: 3;
}, "Error!">, Result.Result<4, never>>(name: "d", fn: (a: {
a: 1;
b: never;
c: 3;
}) => Result.Result<4, never>) => (result: Result.Result<{
a: 1;
b: never;
c: 3;
}, "Error!">) => Result.Result<{
a: 1;
b: never;
c: 3;
d: 4;
}, "Error!"> (+1 overload)
bind ('d', () => import Result Result .const succeed: <4>(value: 4) => Result.Result<4, never> (+1 overload) succeed (4)), // スキップ
);
// { type: 'Failure', error: 'Error!' }#例:関連データの取得
複数の関連リソースを取得して組み合わせる必要がある場合の例。
import { import Result Result } from '@praha/byethrow';
type type OrderDetails = {
orderId: string;
customerName: string;
products: {
id: string;
name: string;
price: number;
}[];
totalPrice: number;
}
OrderDetails = {
orderId: string orderId : string;
customerName: string customerName : string;
products: {
id: string;
name: string;
price: number;
}[]
products : { id: string id : string; name: string name : string; price: number price : number }[];
totalPrice: number totalPrice : number;
};
const const getOrderDetails: (orderId: string) => Result.ResultAsync<OrderDetails, "OrderNotFound" | "UserNotFound" | "ProductNotFound"> getOrderDetails = (orderId: string orderId : string): import Result Result .type ResultAsync<T, E> = Promise<Result.Result<T, E>>An asynchronous variant of
Result
, wrapped in a Promise.
@typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@exampleimport { Result } from '@praha/byethrow';
const fetchData = async (): Result.ResultAsync<string, Error> => {
try {
const data = await fetch('...');
return { type: 'Success', value: await data.text() };
} catch (err) {
return { type: 'Failure', error: err as Error };
}
};
@categoryCore Types ResultAsync <type OrderDetails = {
orderId: string;
customerName: string;
products: {
id: string;
name: string;
price: number;
}[];
totalPrice: number;
}
OrderDetails , 'OrderNotFound' | 'UserNotFound' | 'ProductNotFound'> => {
return import Result Result .const pipe: <Result.Result<{}, never>, Result.ResultAsync<{
order: {
id: string;
userId: string;
productIds: string[];
};
}, "OrderNotFound">, Result.ResultAsync<{
order: {
id: string;
userId: string;
productIds: string[];
};
user: {
id: string;
name: string;
};
}, "OrderNotFound" | "UserNotFound">, Result.ResultAsync<{
order: {
id: string;
userId: string;
productIds: string[];
};
user: {
id: string;
name: string;
};
products: {
id: string;
name: string;
price: number;
}[];
}, "OrderNotFound" | "UserNotFound" | "ProductNotFound">, Result.ResultAsync<{
readonly orderId: string;
readonly customerName: string;
readonly products: {
id: string;
name: string;
price: number;
}[];
readonly totalPrice: number;
}, "OrderNotFound" | ... 1 more ... | "ProductNotFound">>(a: Result.Result<...>, ab: (a: Result.Result<...>) => Result.ResultAsync<...>, bc: (b: Result.ResultAsync<...>) => Result.ResultAsync<...>, cd: (c: Result.ResultAsync<...>) => Result.ResultAsync<...>, de: (d: Result.ResultAsync<...>) => Result.ResultAsync<...>) => Result.ResultAsync<...> (+25 overloads)
pipe (
import Result Result .function do(): import("/home/runner/work/byethrow/byethrow/packages/byethrow/dist/esm/result").Result<{}, never>
export do
Alias for succeed({}). Commonly used as a neutral base value in functional chains or monadic pipelines.
@function@exampleimport { Result } from '@praha/byethrow';
const result = Result.do();
// Result.Result<{}, never>
@categoryCreators do (),
import Result Result .const bind: <"order", Result.Result<{}, never>, Result.ResultAsync<{
id: string;
userId: string;
productIds: string[];
}, "OrderNotFound">>(name: "order", fn: (a: {}) => Result.ResultAsync<{
id: string;
userId: string;
productIds: string[];
}, "OrderNotFound">) => (result: Result.Result<{}, never>) => Result.ResultAsync<{
order: {
id: string;
userId: string;
productIds: string[];
};
}, "OrderNotFound"> (+1 overload)
bind ('order', () => const fetchOrder: (orderId: string) => Result.ResultAsync<{
id: string;
userId: string;
productIds: string[];
}, "OrderNotFound">
fetchOrder (orderId: string orderId )),
import Result Result .const bind: <"user", Result.ResultAsync<{
order: {
id: string;
userId: string;
productIds: string[];
};
}, "OrderNotFound">, Result.ResultAsync<{
id: string;
name: string;
}, "UserNotFound">>(name: "user", fn: (a: {
order: {
id: string;
userId: string;
productIds: string[];
};
}) => Result.ResultAsync<{
id: string;
name: string;
}, "UserNotFound">) => (result: Result.ResultAsync<{
order: {
id: string;
userId: string;
productIds: string[];
};
}, "OrderNotFound">) => Result.ResultAsync<{
order: {
id: string;
userId: string;
productIds: string[];
};
user: {
id: string;
name: string;
};
}, "OrderNotFound" | "UserNotFound"> (+1 overload)
bind ('user', ({ order: {
id: string;
userId: string;
productIds: string[];
}
order }) => const fetchUser: (userId: string) => Result.ResultAsync<{
id: string;
name: string;
}, "UserNotFound">
fetchUser (order: {
id: string;
userId: string;
productIds: string[];
}
order .userId: string userId )),
import Result Result .const bind: <"products", Result.ResultAsync<{
order: {
id: string;
userId: string;
productIds: string[];
};
user: {
id: string;
name: string;
};
}, "OrderNotFound" | "UserNotFound">, Result.ResultAsync<{
id: string;
name: string;
price: number;
}[], "ProductNotFound">>(name: "products", fn: (a: {
order: {
id: string;
userId: string;
productIds: string[];
};
user: {
id: string;
name: string;
};
}) => Result.ResultAsync<{
id: string;
name: string;
price: number;
}[], "ProductNotFound">) => (result: Result.ResultAsync<{
order: {
id: string;
userId: string;
productIds: string[];
};
user: {
id: string;
name: string;
};
}, "OrderNotFound" | "UserNotFound">) => Result.ResultAsync<...> (+1 overload)
bind ('products', ({ order: {
id: string;
userId: string;
productIds: string[];
}
order }) => const fetchProducts: (productIds: string[]) => Result.ResultAsync<{
id: string;
name: string;
price: number;
}[], "ProductNotFound">
fetchProducts (order: {
id: string;
userId: string;
productIds: string[];
}
order .productIds: string[] productIds )),
import Result Result .const map: <Result.ResultAsync<{
order: {
id: string;
userId: string;
productIds: string[];
};
user: {
id: string;
name: string;
};
products: {
id: string;
name: string;
price: number;
}[];
}, "OrderNotFound" | "UserNotFound" | "ProductNotFound">, {
readonly orderId: string;
readonly customerName: string;
readonly products: {
id: string;
name: string;
price: number;
}[];
readonly totalPrice: number;
}>(fn: (a: {
order: {
id: string;
userId: string;
productIds: string[];
};
user: {
id: string;
name: string;
};
products: {
id: string;
name: string;
price: number;
}[];
}) => {
readonly orderId: string;
readonly customerName: string;
readonly products: {
id: string;
name: string;
price: number;
}[];
readonly totalPrice: number;
}) => (result: Result.ResultAsync<...>) => Result.ResultAsync<...> (+1 overload)
map (({ order: {
id: string;
userId: string;
productIds: string[];
}
order , user: {
id: string;
name: string;
}
user , products: {
id: string;
name: string;
price: number;
}[]
products }) => ({
orderId: string orderId : order: {
id: string;
userId: string;
productIds: string[];
}
order .id: string id ,
customerName: string customerName : user: {
id: string;
name: string;
}
user .name: string name ,
products: {
id: string;
name: string;
price: number;
}[]
products ,
totalPrice: number totalPrice : products: {
id: string;
name: string;
price: number;
}[]
products .Array<{ id: string; name: string; price: number; }>.reduce<number>(callbackfn: (previousValue: number, currentValue: {
id: string;
name: string;
price: number;
}, currentIndex: number, array: {
id: string;
name: string;
price: number;
}[]) => number, initialValue: number): number (+2 overloads)
Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
@paramcallbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.@paraminitialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. reduce ((sum: number sum , p: {
id: string;
name: string;
price: number;
}
p ) => sum: number sum + p: {
id: string;
name: string;
price: number;
}
p .price: number price , 0),
})),
);
};
// 注文データを使用してユーザーと製品を取得し、すべてを組み合わせます#リファレンス
| 関数 | 目的 |
|---|---|
| do() | Success<{}>で開始 |
| bind(name, fn) | 蓄積されたオブジェクトにフィールドを追加 |
