typescript(option): feat: added the base helpers
Signed-off-by: prescientmoon <git@moonythm.dev>
This commit is contained in:
parent
052584b09a
commit
b388fb76aa
110
typescript/option/src/helpers.ts
Normal file
110
typescript/option/src/helpers.ts
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
import { Option, Some, None } from './types'
|
||||||
|
import { Binder, Folder, Mapper, Predicate, BackFolder } from './internalTypes'
|
||||||
|
import Internals, { SomeClass } from './internals'
|
||||||
|
|
||||||
|
export const isSome = <T>(option: Option<T>) =>
|
||||||
|
option instanceof Internals.SomeClass
|
||||||
|
export const isNothing = <T>(option: Option<T>) =>
|
||||||
|
option instanceof Internals.NoneClass
|
||||||
|
|
||||||
|
export const match = <T, U>(
|
||||||
|
option: Option<T>,
|
||||||
|
caseSome: (v: T) => U,
|
||||||
|
caseNone: () => U
|
||||||
|
) => {
|
||||||
|
if (isSome(option)) {
|
||||||
|
return caseSome((option as SomeClass<T>)[Internals.someValue])
|
||||||
|
}
|
||||||
|
|
||||||
|
return caseNone()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const bind = <T, U>(
|
||||||
|
binder: Binder<T, U>,
|
||||||
|
option: Option<T>
|
||||||
|
): Option<U> => {
|
||||||
|
return match(option, binder, () => None)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const map = <T, U>(
|
||||||
|
mapper: Mapper<T, U>,
|
||||||
|
option: Option<T>
|
||||||
|
): Option<U> => {
|
||||||
|
return match(
|
||||||
|
option,
|
||||||
|
v => Some(mapper(v)),
|
||||||
|
() => None
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const count = <T>(option: Option<T>) => Number(isSome(option))
|
||||||
|
|
||||||
|
export const exists = <T>(predicate: Predicate<T>, option: Option<T>) => {
|
||||||
|
return match(option, predicate, () => false)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const filter = <T>(predicate: Predicate<T>, option: Option<T>) => {
|
||||||
|
return match(
|
||||||
|
option,
|
||||||
|
v => (predicate(v) ? Some(v) : None),
|
||||||
|
() => None
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fold = <T, U>(
|
||||||
|
folder: Folder<T, U>,
|
||||||
|
initial: U,
|
||||||
|
option: Option<T>
|
||||||
|
) => {
|
||||||
|
match(
|
||||||
|
option,
|
||||||
|
v => folder(initial, v),
|
||||||
|
() => initial
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const foldback = <T, U>(
|
||||||
|
folder: BackFolder<T, U>,
|
||||||
|
option: Option<T>,
|
||||||
|
initial: U
|
||||||
|
) => {
|
||||||
|
return match(
|
||||||
|
option,
|
||||||
|
v => folder(v, initial),
|
||||||
|
() => initial
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const forall = <T>(predicate: Predicate<T>, option: Option<T>) => {
|
||||||
|
return match(option, predicate, () => true)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const get = <T>(option: Option<T>) => {
|
||||||
|
return match(
|
||||||
|
option,
|
||||||
|
v => v,
|
||||||
|
() => {
|
||||||
|
throw new Error('Cannot get value from None')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const iter = <T>(mapper: Mapper<T, void>, option: Option<T>) => {
|
||||||
|
match(option, mapper, () => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const toArray = <T>(option: Option<T>) => {
|
||||||
|
return match(
|
||||||
|
option,
|
||||||
|
v => [v],
|
||||||
|
() => []
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const toNullable = <T>(option: Option<T>) => {
|
||||||
|
return match(
|
||||||
|
option,
|
||||||
|
v => v,
|
||||||
|
() => null
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './helpers'
|
||||||
|
export * from './types'
|
7
typescript/option/src/internalTypes.ts
Normal file
7
typescript/option/src/internalTypes.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { Option } from './types'
|
||||||
|
|
||||||
|
export type Mapper<T, U> = (v: T) => U
|
||||||
|
export type Binder<T, U> = Mapper<T, Option<U>>
|
||||||
|
export type Predicate<T> = Mapper<T, boolean>
|
||||||
|
export type Folder<T, U> = (s: U, v: T) => U
|
||||||
|
export type BackFolder<T, U> = (v: T, s: U) => U
|
17
typescript/option/src/internals.ts
Normal file
17
typescript/option/src/internals.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
export const isOption = Symbol('option')
|
||||||
|
export const someValue = Symbol('value')
|
||||||
|
|
||||||
|
export class SomeClass<T> {
|
||||||
|
public [isOption] = true
|
||||||
|
public [someValue]: T
|
||||||
|
|
||||||
|
public constructor(value: T) {
|
||||||
|
this[someValue] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NoneClass {
|
||||||
|
public [isOption] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
export default { NoneClass, SomeClass, isOption, someValue }
|
6
typescript/option/src/types.ts
Normal file
6
typescript/option/src/types.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import * as Internals from './internals'
|
||||||
|
|
||||||
|
export type Option<T> = Internals.SomeClass<T> | Internals.NoneClass
|
||||||
|
|
||||||
|
export const None = new Internals.NoneClass()
|
||||||
|
export const Some = <T>(v: T) => new Internals.SomeClass(v)
|
Loading…
Reference in a new issue