Can you tell me how to handle multiple Option types?
Closed this issue · 4 comments
I love this library.
Can you tell me how to handle multiple Option types?
Assume there are multiple Option type values.
el1 = string, el2=boolean, el3=number, el4=number[].
In this case, I want to take out the value of el1 to el4 when all of el1 to el4 are Some. if one of el1 to el4 is None, I want to process it as None.
The following is not the correct syntax, but is what I want to do.
match([el1, el2, el3, el4]) => {
Some(el1), Some(el2), Some(el3), Some(el4) => {
// el1 = string, el2 = boolean, el3 = number, el4 = number[]
}
_ => {error}
}
Below is my silly solution that I thought about for 30 minutes
const el1: O.Option<string> = O.Some("3");
const el2: O.Option<boolean> = O.Some(true);
const el3: O.Option<number> = O.Some(4);
const el4: O.Option<string[]> = O.Some(["hello"]);
const optionsResult = O.flatMap(el1, (el1) =>
O.flatMap(el2, (el2) =>
O.flatMap(el3, (el3) => O.flatMap(el4, (el4) => ({ el1, el2, el3, el4 }))),
),
);
I'd prefer ts-pattern
for these scenarios.
const el1: O.Option<string> = O.Some("3");
const el2: O.Option<boolean> = O.Some(true);
const el3: O.Option<number> = O.Some(4);
const el4: O.Option<string[]> = O.Some(["hello"]);
const optionsResult =
match([el1,el2,el3,el4])
.with([P.not(P.nullish),P.not(P.nullish),P.not(P.nullish),P.not(P.nullish)],
([el1,el2,el3,el4])=>({el1,el2,el3,el4}))
.otherwise(F.always(O.None))
I've experienced the same dx issue in the rescript. When handling >3 option types, using pattern matching was much better to read.
in other languages such as purescript or haskell, they have do-notation for this but unfortunately, javascript does not.
I am also a fan of ts-pattern.
I did as you described and it seems to be working well.
Thanks for your help, I appreciate it.
I thought of a utility function during my lunch break.
The following is not type safe as it uses as assertion.
const el1: O.Option<string> = O.Some("hello");
const el2: O.Option<boolean> = O.Some(true);
const el3: O.Option<number> = O.Some(4);
const el4: O.Option<string[]> = O.Some(["hello", "world"]);
type OptionObject<T> = {
[K in keyof T]: Option<T[K]>;
};
const zipAllOption = <T>(
options: OptionObject<T>,
): Option<{ [K in keyof T]: T[K] }> =>
pipe(
options,
D.toPairs,
A.every(([_, v]) => O.isSome(v)),
B.ifElse(
() => options as { [K in keyof T]: T[K] },
() => O.None,
),
);
const optionResult = zipAllOption({ el1, el2, el3, el4 });
I've just found O.all from ts-belt 4.0.0.
const el1: O.Option<string> = O.Some("3");
const el2: O.Option<boolean> = O.Some(true);
const el3: O.Option<number> = O.Some(4);
const el4: O.Option<string[]> = O.Some(["hello"]);
const result =
pipe(
[el1,el2,el3,el4],
O.all,
O.map(([el1,el2,el3,el4])=> /* your function goes here */),
)
This is probably the right function for you.
Thanks!