Created
March 26, 2019 17:37
-
-
Save DragorWW/86587c848d25d529c99e5585e05e53dd to your computer and use it in GitHub Desktop.
Flow type frendly normalize js object by schema
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
// @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