Skip to content

Instantly share code, notes, and snippets.

@velosipedist
Created March 18, 2020 13:40
Show Gist options
  • Save velosipedist/727422edfaef6f108b0652169db56f9c to your computer and use it in GitHub Desktop.
Save velosipedist/727422edfaef6f108b0652169db56f9c to your computer and use it in GitHub Desktop.
Conditional factory to replace `switch(true){}` in functional style
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