Created
March 18, 2020 13:40
-
-
Save velosipedist/727422edfaef6f108b0652169db56f9c to your computer and use it in GitHub Desktop.
Conditional factory to replace `switch(true){}` in functional style
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
type Predicate<T> = (x: T) => boolean; | |
/** | |
* Usage: | |
* ```typescript | |
* const factory = when(something) | |
* .match( (x) => someLogicReturningTrue ) | |
* .then( () => anyLogicToProduceResult ) | |
* .byDefault( () => defaultLogicWhenNoMatches ) | |
* | |
* // later in code | |
* const result = factory.make() | |
* ``` | |
* @param subject | |
*/ | |
export function when<T>(subject: T) { | |
let factories: ( | |
{ | |
pred: Predicate<T>, | |
factory: Function, | |
} | |
)[] = []; | |
let predicateQueued: (Predicate<T>) | null = null; | |
let defaultFactory: Function | null = null; | |
const matcher = { | |
match: (predicate: Predicate<T>) => { | |
predicateQueued = predicate; | |
return matcher; | |
}, | |
then: (factory: Function) => { | |
if (predicateQueued === null) { | |
throw 'Missing .is() call before .then()'; | |
} | |
factories.push({ | |
pred: predicateQueued, | |
factory: factory, | |
}); | |
predicateQueued = null; | |
return matcher; | |
}, | |
byDefault: (factory: Function) => { | |
defaultFactory = factory; | |
return matcher; | |
}, | |
make: () => { | |
if (defaultFactory === null) { | |
throw 'Use .byDefault() as a default factory'; | |
} | |
const found = factories.find(({ pred }) => pred(subject)); | |
if (found) { | |
return found.factory(); | |
} | |
return defaultFactory(); | |
}, | |
}; | |
return matcher; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment