Created
June 11, 2024 19:09
-
-
Save Shoghy/8f3c8c499abfb3a02170acc75b4e8830 to your computer and use it in GitHub Desktop.
Imitando los enum Option y Result de Rust
This file contains 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
enum EType { | |
Some, | |
None, | |
} | |
export class Option<T> { | |
private value!: T; | |
private type: EType; | |
private constructor(type: EType) { | |
this.type = type; | |
} | |
static Some<T>(value: T): Option<T> { | |
const self = new Option<T>(EType.Some); | |
self.value = value; | |
return self; | |
} | |
static None<T>(): Option<T> { | |
return new Option(EType.None); | |
} | |
is_some(): boolean { | |
return this.type == EType.Some; | |
} | |
is_none(): boolean { | |
return this.type == EType.None; | |
} | |
inspect(func: (value: T) => unknown): this { | |
if (!this.is_some()) return this; | |
func(this.value); | |
return this; | |
} | |
or(optb: Option<T>): Option<T> { | |
if (this.is_some()) { | |
return this; | |
} | |
if (optb.is_some()) { | |
return optb; | |
} | |
return Option.None(); | |
} | |
or_else(func: () => Option<T>): Option<T> { | |
if (this.is_some()) { | |
return this; | |
} | |
return func(); | |
} | |
xor(optb: Option<T>): Option<T> { | |
if (this.is_some()) { | |
if (optb.is_some()) { | |
return Option.None(); | |
} | |
return this; | |
} | |
if (optb.is_some()) { | |
return optb; | |
} | |
return Option.None(); | |
} | |
and<U>(optb: Option<U>): Option<U> { | |
if (this.is_some() && optb.is_some()) { | |
return optb; | |
} | |
return Option.None(); | |
} | |
and_then<U>(func: (value: T) => Option<U>): Option<U> { | |
if (this.is_some()) { | |
return func(this.value); | |
} | |
return Option.None(); | |
} | |
expect(msg: string): T { | |
if (this.is_some()) { | |
return this.value; | |
} | |
throw new Error(msg); | |
} | |
get_or_insert(value: T): T { | |
if (this.is_none()) { | |
this.value = value; | |
this.type = EType.Some; | |
} | |
return this.value; | |
} | |
get_or_insert_with(func: () => T): T { | |
if (this.is_none()) { | |
this.value = func(); | |
this.type = EType.Some; | |
} | |
return this.value; | |
} | |
insert(value: T): T { | |
this.value = value; | |
this.type = EType.Some; | |
return this.value; | |
} | |
is_some_and(func: (value: T) => boolean): boolean { | |
if (this.is_none()) { | |
return false; | |
} | |
return func(this.value); | |
} | |
take(): Option<T> { | |
if (this.is_none()) { | |
return Option.None(); | |
} | |
const value = this.value; | |
this.value = null as any; | |
this.type = EType.None; | |
return Option.Some(value); | |
} | |
unwrap(): T { | |
if (this.is_some()) { | |
return this.value; | |
} | |
throw new Error("`Option` is None"); | |
} | |
unwrap_or(value: T): T { | |
if (this.is_some()) { | |
return this.value; | |
} | |
return value; | |
} | |
unwrap_or_else(func: () => T): T { | |
if (this.is_some()) { | |
return this.value; | |
} | |
return func(); | |
} | |
zip<U>(other: Option<U>): Option<[T, U]> { | |
if (this.is_none() || other.is_none()) { | |
return Option.None(); | |
} | |
return Option.Some([this.value, other.value]); | |
} | |
to_string(): string { | |
if (this.is_some()) { | |
return `Some(${this.value})`; | |
} | |
return "None"; | |
} | |
} | |
export const Some = Option.Some; | |
export const None = Option.None; |
This file contains 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
import { None, Option, Some } from "./option"; | |
enum EType { | |
Ok, | |
Err, | |
} | |
export class Result<T, E> { | |
private type: EType; | |
private value!: T | E; | |
private constructor(type: EType) { | |
this.type = type; | |
} | |
static Ok<T>(value: T): Result<T, unknown> { | |
const self = new Result<T, unknown>(EType.Ok); | |
self.value = value; | |
return self; | |
} | |
static Err<E>(value: E): Result<unknown, E> { | |
const self = new Result<unknown, E>(EType.Err); | |
self.value = value; | |
return self; | |
} | |
is_ok(): boolean { | |
return this.type == EType.Ok; | |
} | |
is_err(): boolean { | |
return this.type == EType.Err; | |
} | |
inspect(func: (ok: T) => unknown): this { | |
if (this.is_err()) return this; | |
func(this.value as T); | |
return this; | |
} | |
inspect_err(func: (err: E) => unknown): this { | |
if (this.is_ok()) return this; | |
func(this.value as E); | |
return this; | |
} | |
and<U>(res: Result<U, E>) { | |
if (this.is_err()) { | |
return this; | |
} | |
return res; | |
} | |
and_then<U>(func: (value: T) => Result<U, E>) { | |
if (this.is_err()) { | |
return this; | |
} | |
return func(this.value as T); | |
} | |
err(): Option<E> { | |
if (this.is_ok()) { | |
return None(); | |
} | |
return Some(this.value as E); | |
} | |
expect(value: string): T { | |
if (this.is_ok()) { | |
return this.value as T; | |
} | |
throw new Error(value); | |
} | |
expect_err(value: string): E { | |
if (this.is_err()) { | |
return this.value as E; | |
} | |
throw new Error(value); | |
} | |
is_err_and(func: (err: E) => boolean): boolean { | |
if (this.is_ok()) { | |
return false; | |
} | |
return func(this.value as E); | |
} | |
is_ok_and(func: (ok: T) => boolean): boolean { | |
if (this.is_err()) { | |
return false; | |
} | |
return func(this.value as T); | |
} | |
map<U>(func: (ok: T) => Result<U, E>) { | |
if (this.is_err()) { | |
return this; | |
} | |
return func(this.value as T); | |
} | |
map_err<F>(func: (err: E) => Result<T, F>) { | |
if (this.is_ok()) { | |
return this; | |
} | |
return func(this.value as E); | |
} | |
map_or<U>(def: U, func: (ok: T) => U): U { | |
if (this.is_err()) { | |
return def; | |
} | |
return func(this.value as T); | |
} | |
map_or_else<U>(err_func: (err: E) => U, ok_func: (ok: T) => U): U { | |
if (this.is_err()) { | |
return err_func(this.value as E); | |
} | |
return ok_func(this.value as T); | |
} | |
ok(): Option<T> { | |
if (this.is_err()) { | |
return None(); | |
} | |
return Some(this.value as T); | |
} | |
or<F>(res: Result<T, F>) { | |
if (this.is_ok()) { | |
return this; | |
} | |
return res; | |
} | |
or_else<F>(op: (err: E) => Result<T, F>) { | |
if (this.is_ok()) { | |
return this; | |
} | |
return op(this.value as E); | |
} | |
unwrap(): T { | |
if (this.is_ok()) { | |
return this.value as T; | |
} | |
throw new Error("`Result` is Err"); | |
} | |
unwrap_err(): E { | |
if (this.is_err()) { | |
return this.value as E; | |
} | |
throw new Error("`Result` is Ok"); | |
} | |
unwrap_or(def: T): T { | |
if (this.is_ok()) { | |
return this.value as T; | |
} | |
return def; | |
} | |
unwrap_or_else(func: (err: E) => T): T { | |
if (this.is_ok()) { | |
return this.value as T; | |
} | |
return func(this.value as E); | |
} | |
to_string(): string { | |
if (this.is_ok()) { | |
return `Ok(${this.value})`; | |
} | |
return `Err(${this.value})`; | |
} | |
} | |
export const Ok = Result.Ok; | |
export const Err = Result.Err; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment