Skip to content

Instantly share code, notes, and snippets.

@1216892614
Last active September 11, 2024 06:09
Show Gist options
  • Save 1216892614/2406e3950bcf60ab616ec7098e19df74 to your computer and use it in GitHub Desktop.
Save 1216892614/2406e3950bcf60ab616ec7098e19df74 to your computer and use it in GitHub Desktop.
mayErr
// deno-lint-ignore-file no-explicit-any
type FlatMonad<T> = T extends MayErr<
infer InnerE,
infer InnerT,
infer InnerIsSuccessful
>
? InnerIsSuccessful extends true
? FlatMonad<InnerT>
: InnerE
: T;
export class MayErr<E extends Error = Error, T = any, IsSuccessful = boolean> {
#isSuccessful: IsSuccessful;
#val: IsSuccessful extends true ? T : null;
#err: IsSuccessful extends true ? null : E;
private constructor(
isSuccessful: IsSuccessful,
val: IsSuccessful extends true ? T : null,
err: IsSuccessful extends true ? null : E
) {
this.#isSuccessful = isSuccessful;
this.#val = val;
this.#err = err;
}
static mayErr =
<E extends Error, const F extends (...args: any) => any>(f: F) =>
(
...p: Parameters<F>
):
| MayErr<E, FlatMonad<ReturnType<F>>, true>
| MayErr<E, FlatMonad<ReturnType<F>>, false> => {
try {
const ret = f(...p);
if (!(ret instanceof MayErr))
return new MayErr<E, FlatMonad<ReturnType<F>>, true>(
true,
ret,
null
);
return new MayErr<E, FlatMonad<ReturnType<F>>, true>(
true,
ret.flat,
null
);
} catch (err) {
return new MayErr<E, FlatMonad<ReturnType<F>>, false>(
false,
null,
err as E
);
}
};
get isSuccessful() {
return this.#isSuccessful;
}
get val() {
return this.#val;
}
private get flat(): FlatMonad<typeof this> {
if (!(this.#val instanceof MayErr)) return (this.#val as MayErr).flat;
return this.#val as FlatMonad<typeof this>;
}
get err() {
return this.#err;
}
map<NewErr extends Error = Error, NewT = any>(f: (v: T) => NewT) {
type Res = IsSuccessful extends false
? MayErr<NewErr, NewT, boolean>
: typeof this;
if (!this.#isSuccessful) return this as Res;
return MayErr.mayErr<NewErr, (v: T) => NewT>(f)(this.val as T) as Res;
}
}
export default MayErr.mayErr;
@1216892614
Copy link
Author

TODO: mayErr 没法仅推导 F 而传入 E, 这个问题目前不知道怎么优化

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment