const isObjectOf = schema => obj => {
Object.keys(schema).forEach(key => {
const value = obj[key]
const predicate = schema[key]
try {
if (predicate(value) === false) {
throw new Error('invalid')
}
} catch(err) {
throw new Error(`${key} ${err.message}`)
}
})
return true
}
const isArrayOf = predicate => arr => {
arr.forEach((value, i) => {
try {
if (predicate(value) === false) {
throw new Error('invalid')
}
} catch(err) {
throw new Error(`[${i}] ${err.message}`)
}
})
}
const isRequired = predicate => value => {
if (value === undefined) {
throw new Error('missing')
} else {
return predicate(value)
}
}
const isOptional = predicate => value => {
if (value === undefined) {
return true
} else {
return predicate(value)
}
}
const isString = isOptional(s => typeof s === 'string')
const isNumber = isOptional(n => typeof n === 'number')
const isMyType = isObjectOf({
foo: isString,
bar: isRequired(isNumber),
arr: isArrayOf(isNumber)
})
isMyOtherType = isObjectOf({
baz: isString,
myType: isRequired(isMyType)
})
isMyOtherType({
baz: 'dop',
myType:{
// foo: 'fo',
// bar: 3,
arr: [3, 3]
}
})