Last active
September 11, 2024 06:09
-
-
Save 1216892614/2406e3950bcf60ab616ec7098e19df74 to your computer and use it in GitHub Desktop.
mayErr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
TODO:
mayErr
没法仅推导F
而传入E
, 这个问题目前不知道怎么优化