ts-cast
Version:
Runtime typechecking
38 lines (37 loc) • 1.37 kB
JavaScript
import { createCaster } from '../engine';
import { isAnObj } from '../engine/guards';
import optional from '../engine/optional';
const transformStruct = (schema, ref) => {
const fields = Object.entries(schema);
return (value, context, reportError) => fields.reduce((target, [field, caster]) => Object.defineProperty(target, field, {
enumerable: true,
writable: true,
configurable: true,
value: caster(value[field], context ? `${context}.${String(field)}` : `${String(field)}`, reportError),
}), Object.create(ref.caster.prototype));
};
const partial = (schema) => Object.keys(schema).reduce((newSchema, field) => {
newSchema[field] = optional(schema[field]);
return newSchema;
}, Object.create(null));
export const struct = (schema, typeName = 'struct') => {
const ref = {};
const caster = Object.defineProperties(createCaster(typeName, isAnObj, transformStruct(schema, ref)), {
name: {
value: typeName,
},
partial: {
enumerable: true,
get: () => struct(partial(schema), `Partial<${typeName}>`),
},
});
ref.caster = Object.defineProperty(caster, 'prototype', {
enumerable: false,
configurable: false,
writable: true,
value: {
constructor: caster,
},
});
return caster;
};