Skip to content

Instantly share code, notes, and snippets.

@StarpTech
Last active October 29, 2018 12:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StarpTech/3b009eec086a800f1575c129d08e7f02 to your computer and use it in GitHub Desktop.
Save StarpTech/3b009eec086a800f1575c129d08e7f02 to your computer and use it in GitHub Desktop.
Small library to validate numeric data structures in a functional-style
/**
* Small library to validate numeric data structures in a functional-style
* All functions are right associative
* If you are looking for more sophisticated features have a look at
* https://ramdajs.com/
*/
export interface FabPattern {
[index: string]: (input: number) => boolean;
}
export class Fab {
static gt(...mem: number[]) {
return (input: number) => mem.every(m => input > m);
}
static lt(...mem: number[]) {
return (input: number) => mem.every(m => input < m);
}
static lte(...mem: number[]) {
return (input: number) => mem.every(m => input <= m);
}
static gte(...mem: number[]) {
return (input: number) => mem.every(m => input >= m);
}
static equals(...mem: number[]) {
return (input: number) => mem.every(m => input === m);
}
static and(...mem: Function[]) {
return (input: number) => mem.every(m => m(input));
}
static either(...mem: Function[]) {
return (input: number) => mem.findIndex(m => m(input)) > -1;
}
/**
* Validate the pattern and returns the result
* @param pattern
*/
static where(pattern: FabPattern) {
return (obj: {[key: string]: any}) => {
for (const key in pattern) {
const check = pattern[key];
const input = obj[key];
if (key in obj && typeof check === 'function') {
if (check(input) === false) return false;
}
}
return true;
};
}
/**
* Validate the pattern and resolve with a value or default value
* @param pattern
* @param value
* @param defaultValue
*/
static cond(pattern: FabPattern, value: any, defaultValue?: any) {
return (obj: {[key: string]: any}) => {
if (Fab.where(pattern)(obj)) {
return value;
}
return defaultValue;
};
}
/**
* Validates an array of "cond" and returns the first match
* @param mem
*/
static anyCond(...mem: Function[]) {
return (obj: {[key: string]: any}) => {
for (const m of mem) {
const result = m(obj);
if (result) {
return result;
}
}
};
}
}
const validate = Fab.where({
a: Fab.and(
Fab.gt(100),
Fab.lte(300),
Fab.either(Fab.equals(200), Fab.equals(220))
),
b: Fab.equals(0.15),
c: Fab.either(Fab.equals(0), Fab.equals(2), Fab.equals(3))
});
console.log(validate({ a: 220, b: 0.15, c: 3 }));
console.log(validate({ a: 199, b: 0 }));
const validate2 = Fab.cond(
{
a: Fab.and(Fab.gt(100), Fab.lte(300))
},
"foo"
);
console.log(validate2({ a: 200 }));
const validate3 = Fab.anyCond(
Fab.cond(
{
a: Fab.and(Fab.gt(100), Fab.lte(300))
},
"foo"
),
Fab.cond(
{
a: Fab.and(Fab.gt(500), Fab.lte(800))
},
"bar"
)
);
console.log(validate3({ a: 200 }));
console.log(validate3({ a: 600 }));
console.log(validate3({ a: 900 }));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment