Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor to result, option classes #15

Merged
merged 12 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions src/error/util.ts

This file was deleted.

File renamed without changes.
21 changes: 21 additions & 0 deletions src/fn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type {Result} from "./result"
import {PromiseResult} from "./promise_result"
import type {InferErr, InferOk} from "./internal"

export function fn<A extends any[], R extends Result<any, any>>(
f: (...args: A) => R,
): (...args: A) => Result<InferOk<R>, InferErr<R>> {
return f
}

export function asyncFn<A extends any[], R extends PromiseResult<any, any>>(
f: (...args: A) => R,
): (...args: A) => PromiseResult<InferOk<Awaited<R>>, InferErr<Awaited<R>>>
export function asyncFn<A extends any[], R extends Promise<Result<any, any>>>(
f: (...args: A) => R,
): (...args: A) => PromiseResult<InferOk<Awaited<R>>, InferErr<Awaited<R>>>
export function asyncFn(f: any): any {
return function (...args: any[]) {
return new PromiseResult(f(...args))
}
}
6 changes: 3 additions & 3 deletions src/helpers/group.ts → src/group.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {tryAsyncFnWith, tryFnWith, tryPromiseWith} from "./try"
import type {ErrorHandler} from "../error/result_error"
import type {Result} from "../result/result"
import type {PromiseResult} from "../result/promise"
import type {ErrorHandler} from "./result_error"
import type {Result} from "./result"
import type {PromiseResult} from "./promise_result"

type Fn = (...args: any[]) => any
type AsyncFn = (...args: any[]) => Promise<any>
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/guard.ts → src/guard.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {type ErrorHandler, type ResultError} from "../error/result_error"
import {type ErrorHandler, type ResultError} from "./result_error"
import {tryAsyncFn, tryAsyncFnWith, tryFn, tryFnWith} from "./try"

export function guard<A extends any[], T>(f: (...args: A) => T) {
Expand Down
40 changes: 0 additions & 40 deletions src/helpers/fn.ts

This file was deleted.

28 changes: 10 additions & 18 deletions src/internal.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
export * from "./error/panic"
export * from "./error/result_error"

export * from "./helpers/fn"
export * from "./helpers/group"
export * from "./helpers/guard"
export * from "./helpers/try"

export * from "./option/option"
export * from "./option/none"
export * from "./option/promise"
export * from "./option/some"

export * from "./result/result"
export * from "./result/err"
export * from "./result/ok"
export * from "./result/promise"

export * from "./fn"
export * from "./group"
export * from "./guard"
export * from "./option"
export * from "./panic"
export * from "./promise_option"
export * from "./promise_result"
export * from "./result_error"
export * from "./result"
export * from "./try"
export * from "./util"
120 changes: 120 additions & 0 deletions src/option.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import {Panic, UnwrapPanic} from "./panic"
import {inspectSymbol} from "./util"

export class OptionImpl<T> {
readonly some: boolean
readonly none: boolean
readonly value: T | null

constructor(some: boolean, value: T) {
this.some = some
this.none = !some
this.value = value
}

and<U>(other: Option<U>): Option<T | U> {
return (this.some ? other : None) as Option<T | U>
}

andThen<U>(f: (value: T) => Option<U>): Option<T | U> {
return (this.some ? f(this.value as T) : None) as Option<T | U>
}

expect(panic: string): T {
if (this.some) {
return this.value as T
}
throw new Panic(panic)
}

filter(f: (value: T) => boolean): Option<T> {
return (this.some && f(this.value as T) ? this : None) as Option<T>
}

inspect(f: (value: T) => void): this {
if (this.some) {
f(this.value as T)
}
return this
}

map<U>(f: (value: T) => U): Option<T | U> {
return (this.some ? new OptionImpl(true, f(this.value as T)) : None) as Option<T | U>
}

mapOr<A, B>(defaultValue: A, f: (value: T) => B): A | B {
return this.some ? f(this.value as T) : defaultValue
}

mapOrElse<A, B>(defaultValue: () => A, f: (value: T) => B): A | B {
return this.some ? f(this.value as T) : defaultValue()
}

or<U>(other: Option<U>): Option<T | U> {
return (this.some ? this : other) as Option<T | U>
}

orElse<U>(f: () => Option<U>): Option<T | U> {
return (this.some ? this : f()) as Option<T | U>
}

unwrap(): T {
if (this.some) {
return this.value as T
}
throw new UnwrapPanic(`called "unwrap()" on ${this.toString()}`)
}

unwrapOr<U>(defaultValue: U): T | U {
return this.some ? (this.value as T) : defaultValue
}

unwrapOrElse<U>(defaultValue: () => U): T | U {
return this.some ? (this.value as T) : defaultValue()
}

xor<U>(other: Option<U>): Option<T | U> {
if (this.some) {
return (other.some ? None : this) as Option<T | U>
}
return (other.some ? other : None) as Option<T | U>
}

match<A, B>(some: (value: T) => A, none: () => B): A | B {
return this.some ? some(this.value as T) : none()
}

toString(): `Some(${string})` | "None" {
return this.some ? `Some(${this.value})` : "None"
}

[inspectSymbol](): ReturnType<OptionImpl<T>["toString"]> {
return this.toString()
}

toObject(): {some: true; value: T} | {some: false; value: null} {
return this.some ? {some: true, value: this.value as T} : {some: false, value: null}
}

toJSON(): {meta: "Some"; value: T} | {meta: "None"; value: null} {
return this.some ? {meta: "Some", value: this.value as T} : {meta: "None", value: null}
}
}

export interface Some<T> extends OptionImpl<T> {
readonly some: true
readonly none: false
readonly value: T
}
export function Some<T>(value: T): Some<T> {
return new OptionImpl(true, value) as Some<T>
}

export interface None extends OptionImpl<never> {
readonly some: false
readonly none: true
readonly value: null
}
export const None = new OptionImpl(false, null) as None

export type Option<T> = (Some<T> | None) & OptionImpl<T>
88 changes: 0 additions & 88 deletions src/option/none.ts

This file was deleted.

29 changes: 0 additions & 29 deletions src/option/option.ts

This file was deleted.

Loading