Skip to content

Instantly share code, notes, and snippets.

@3AHAT0P
Created June 24, 2022 20:25
Show Gist options
  • Save 3AHAT0P/3d8d2dea6571028d783b656e7c39d911 to your computer and use it in GitHub Desktop.
Save 3AHAT0P/3d8d2dea6571028d783b656e7c39d911 to your computer and use it in GitHub Desktop.
Insane FP Switch
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