Skip to content

Instantly share code, notes, and snippets.

@Shoghy
Created June 11, 2024 19:09
Show Gist options
  • Save Shoghy/8f3c8c499abfb3a02170acc75b4e8830 to your computer and use it in GitHub Desktop.
Save Shoghy/8f3c8c499abfb3a02170acc75b4e8830 to your computer and use it in GitHub Desktop.
Imitando los enum Option y Result de Rust
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;
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