Created
June 24, 2022 20:25
-
-
Save 3AHAT0P/3d8d2dea6571028d783b656e7c39d911 to your computer and use it in GitHub Desktop.
Insane FP Switch
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
const Selector = { | |
}; | |
interface CaseLine<T, G> { | |
condition(value: T): boolean; | |
body(value: T): void | G; | |
} | |
interface Switcher<T, G> { | |
case(caseLine: CaseLine<T, G>): this; | |
getResult(value: T): void | G; | |
match(value: T): void; | |
} | |
interface RETURN<T> { | |
(value: T): T; | |
} | |
interface THROW { | |
(error: Error | string): never; | |
isNothing(): never; | |
} | |
const THROW = (error: string | Error): never => { throw error; }; | |
THROW.isNothing = THROW.bind(null, new Error('Variable is null or undefined')); | |
const RETURN = <T>(value: T): T => value; | |
const SWITCH = <T, G = unknown>(): Switcher<T, G> => { | |
const state: CaseLine<T, G>[] = []; | |
const switcher: Switcher<T, G> = { | |
case(caseLine) { | |
state.push(caseLine); | |
return switcher; | |
}, | |
getResult(value) { | |
for (const {condition, body} of state) { | |
if (condition(value)) return body(value); | |
} | |
}, | |
match(value) { | |
for (const {condition, body} of state) { | |
if (condition(value)) body(value); | |
} | |
}, | |
}; | |
return switcher; | |
}; | |
interface RunnableCaseLine<T, G> extends CaseLine<T, G> { | |
run(value: T): G | void; | |
} | |
interface IFTHEN<T, G> { | |
(body: (value: T) => void | G): RunnableCaseLine<T, G>; | |
return: RunnableCaseLine<T, T>; | |
throw: RunnableCaseLine<T, never> & { | |
isNothing: RunnableCaseLine<T, never>; | |
}; | |
} | |
interface IFResult<T, G> { | |
then: IFTHEN<T, G>; | |
} | |
interface IF<T, G = unknown> { | |
(condition: (value: T) => boolean): IFResult<T, G>; | |
isEqual(target: T): IFResult<T, G>; | |
isInstanceOf(target: new (...args: any[]) => T): IFResult<T, G>; | |
isGTE(target: T): IFResult<T, G>; | |
isLTE(target: T): IFResult<T, G>; | |
isNothing: IFResult<T, G>; | |
isVoid: IFResult<T, G>; | |
isNull: IFResult<T, G>; | |
} | |
const runCaseLine = <T, G>({condition, body}: CaseLine<T, G>) => { | |
return (value: T) => condition(value) ? body(value) : void 0; | |
}; | |
const IF = <T, G = unknown>(condition: (value: T) => boolean): IFResult<T, G> => { | |
const result: any = { | |
then(body: (value: any) => void) { | |
return {condition, body, run: runCaseLine({ condition, body })}; | |
}, | |
}; | |
result.then.return = result.then(RETURN); | |
result.then.throw = result.then(THROW); | |
result.then.throw.isNothing = result.then(THROW.isNothing); | |
return result; | |
}; | |
IF.isEqual = <T, G = unknown>(target: T) => IF<T, G>((value) => value === target); | |
IF.isInstanceOf = <T, G = unknown>(target: new (...args: any[]) => T) => IF<T, G>((value) => value instanceof target); | |
IF.isGTE = <T, G = unknown>(target: T) => IF<T, G>((value) => value >= target); | |
IF.isLTE = <T, G = unknown>(target: T) => IF<T, G>((value) => value <= target); | |
IF.isNothing = IF<unknown>((value) => value == null); | |
IF.isVoid = IF<unknown>((value) => value === void 0); | |
IF.isNull = IF<unknown>((value) => value === null); | |
SWITCH<number>() | |
.case(IF(value => value === 1).then(value => { (window as any).x = value; })) | |
.case(IF<number>(value => value > 4).then(console.log)) | |
.case(IF.isNothing.then(THROW.isNothing)) | |
.case(IF.isNothing.then.throw.isNothing) | |
.match(5); | |
const x = SWITCH<number, number>() | |
.case(IF.isEqual<number, number>(5).then(RETURN)) | |
.case(IF.isEqual(5).then.return) | |
.getResult(5); | |
IF.isNothing.then.throw.isNothing.run(10); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment