Skip to content

Instantly share code, notes, and snippets.

@DragorWW
Created March 26, 2019 17:37
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 DragorWW/86587c848d25d529c99e5585e05e53dd to your computer and use it in GitHub Desktop.
Save DragorWW/86587c848d25d529c99e5585e05e53dd to your computer and use it in GitHub Desktop.
Flow type frendly normalize js object by schema
// @flow
type ExtractReturnType = <V>(() => V) => V;
type ExtractReturnOptionalType = <V>(() => V) => ?V;
export const schema = {
default<T: string | number | {} | boolean | []>(
fn: mixed => ?T,
defaultValue: T | (() => T)
): mixed => T {
const newFn = (i: mixed): T => {
if (typeof defaultValue === 'function') {
return fn(i) || defaultValue();
}
return fn(i) || defaultValue;
};
newFn._originalFn = fn;
newFn.defaultValue = defaultValue;
return newFn;
},
obj<O: {[key: string]: Function}>(
s: O
): mixed => $ObjMap<O, ExtractReturnType> {
const newFn = i => {
return normalize(i, s);
};
newFn._schema = s;
return newFn;
},
array<T: string | number | boolean>(
fn: mixed => ?T,
defaultValue: T[] | (() => T[]) = []
): mixed => T[] {
return (i: mixed) => {
const arr: T[] = [];
if (Array.isArray(i)) {
i.forEach(c => {
if (typeof c !== 'undefined' && c !== null) {
const val = fn(c);
if (typeof val !== 'undefined' && val !== null) {
arr.push(val);
}
}
});
} else {
if (typeof i !== 'undefined' && i !== null) {
const val = fn(i);
if (typeof val !== 'undefined' && val !== null) {
arr.push(val);
}
}
}
if (Array.isArray(defaultValue) && arr.length === 0) {
return defaultValue;
}
return arr;
};
},
number(i: mixed): ?number {
if (typeof i !== 'undefined' && i !== null && i !== '' && !isNaN(+i)) {
return +i;
}
},
bool(i: mixed): ?boolean {
if (typeof i !== 'undefined') {
if (typeof i === 'boolean') {
return i;
} else if (typeof i === 'string') {
if (i === 'false') {
return false;
}
return !!i || /^(true|t|1)$/i.test(i);
} else if (typeof i === 'number') {
return i > 0;
} else if (i instanceof Object) {
return true;
}
return false;
}
},
string(i: mixed): ?string {
if (typeof i !== 'undefined' && i !== null && i !== '') {
return String(i);
}
},
enumerable<+E: string | number>(arr: $ReadOnlyArray<E>): mixed => ?E {
return (i: mixed) => {
if ((typeof i === 'string' || typeof i === 'number') && i in arr) {
// flow не корректно обрабатывает `i in arr`
// Тут все верно работает
// $FlowFixMe
return i;
}
};
},
};
export function normalize<O: {[key: string]: Function}>(
data: mixed,
schema: O
): $ObjMap<O, ExtractReturnType> {
let newData = {};
Object.keys(schema).forEach(key => {
// Проверка нужна так как data может не быть или это будет null
// так как typeof null === 'object';
const param = data instanceof Object ? data[key] : undefined;
newData[key] = schema[key](param);
});
return newData;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment