You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

80 lines
2.0 KiB

import is from '@sindresorhus/is';
import {BasePredicate} from '../..';
import test from '../test';
import {isPredicate} from '../predicates/base-predicate';
export interface Shape {
[key: string]: BasePredicate | Shape;
}
/**
* Test if the `object` matches the `shape` partially.
*
* @hidden
* @param object Object to test against the provided shape.
* @param shape Shape to test the object against.
* @param parent Name of the parent property.
*/
export function partial(object: {[key: string]: any; }, shape: Shape, parent?: string): boolean | string {
try {
for (const key of Object.keys(shape)) {
const label = parent ? `${parent}.${key}` : key;
if (isPredicate(shape[key])) {
test(object[key], label, shape[key] as BasePredicate);
} else if (is.plainObject(shape[key])) {
const result = partial(object[key], shape[key] as Shape, label);
if (result !== true) {
return result;
}
}
}
return true;
} catch (error) {
return error.message;
}
}
/**
* Test if the `object` matches the `shape` exactly.
*
* @hidden
* @param object Object to test against the provided shape.
* @param shape Shape to test the object against.
* @param parent Name of the parent property.
*/
export function exact(object: {[key: string]: any; }, shape: Shape, parent?: string): boolean | string {
try {
const objectKeys = new Set<string>(Object.keys(object));
for (const key of Object.keys(shape)) {
objectKeys.delete(key);
const label = parent ? `${parent}.${key}` : key;
if (isPredicate(shape[key])) {
test(object[key], label, shape[key] as BasePredicate);
} else if (is.plainObject(shape[key])) {
const result = exact(object[key], shape[key] as Shape, label);
if (result !== true) {
return result;
}
}
}
if (objectKeys.size > 0) {
const key = Array.from(objectKeys.keys())[0];
const label = parent ? `${parent}.${key}` : key;
return `Did not expect property \`${label}\` to exist, got \`${object[key]}\``;
}
return true;
} catch (error) {
return error.message;
}
}