ts-cast
Version:
Runtime typechecking
34 lines (33 loc) • 1.24 kB
JavaScript
import { casterApi } from '../engine';
import { throwTypeError } from '../engine/throw-type-error';
import { withName } from '../helpers/names';
const checkTypes = (casters, typeName) => {
const unionCasterFn = (value, context, reportError = throwTypeError) => {
let match;
const errors = [];
const isMatched = casters.some(caster => {
try {
match = caster(value, context);
return true;
}
catch (err) {
errors.push(`${caster.name}: ${err.message}`);
return false;
}
});
if (isMatched)
return match;
return reportError(`${typeName} is expected${context ? ` in ${context}` : ''} but no matching type was found:\n${errors.map(e => ` - ${e}`).join('\n')}`, context);
};
return unionCasterFn;
};
export const union = (...casters) => {
if (casters.length < 2) {
throw new Error('At least two types should be specified.');
}
const typeName = casters.map(c => c.name).join('|');
const casterFn = checkTypes(casters, typeName);
return casterApi(withName(casterFn, typeName));
};
export const firstOf = union;
export const oneOf = union;