Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add array.exactShape predicate #187

Merged
merged 13 commits into from
Jan 19, 2021
23 changes: 23 additions & 0 deletions source/predicates/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import isEqual = require('lodash.isequal');
import {BasePredicate} from './base-predicate';
import {Predicate, PredicateOptions} from './predicate';
import ow from '..';
import {Shape} from './object';
import {exact} from '../utils/match-shape';

export class ArrayPredicate<T = unknown> extends Predicate<T[]> {
/**
Expand Down Expand Up @@ -158,4 +160,25 @@ export class ArrayPredicate<T = unknown> extends Predicate<T[]> {
}
});
}

/**
Test all elements in the array to match the exact shape with the provided predicate.

The predicates is an array which describes how the tested array should look like. Each predicate placed at the nth index should be applied also to the item at the same index.

@param predicates - The predicate placed at the nth index should be applied also to the item at the same index.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just repeating the above. It should actually describe what predicates is.


@example
```
ow(['1', 2], ow.array.exactShape([ow.string, ow.number]));
```
*/
exactShape(predicates: Predicate[]) {
const shape = predicates as unknown as Shape;

return this.addValidator({
message: (_, label, message) => `${message.replace('Expected', 'Expected property')} in ${label}`,
validator: object => exact(object, shape)
});
}
}
18 changes: 18 additions & 0 deletions test/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,21 @@ test('array.ofType', t => {
ow(['foo', 'b'], 'foo', ow.array.ofType(ow.string.minLength(3)));
}, '(array `foo`) Expected string to have a minimum length of `3`, got `b`');
});

test('array.exactShape', t => {
t.notThrows(() => {
ow(['🦄', 2, 3, true, {isFirstCommit: true}], ow.array.exactShape([ow.string, ow.number, ow.number, ow.boolean, ow.object.exactShape({isFirstCommit: ow.boolean})]));
});

t.throws(() => {
ow(['🦄', 2, 'nope', true, {isFirstCommit: true}], ow.array.exactShape([ow.string, ow.number, ow.number, ow.boolean, ow.object.exactShape({isFirstCommit: ow.string})]));
}, 'Expected property `2` to be of type `number` but received type `string` in array');
sindresorhus marked this conversation as resolved.
Show resolved Hide resolved

t.throws(() => {
ow(['🦄', 'nope', {isFirstCommit: true}], ow.array.exactShape([ow.string, ow.string, ow.object.exactShape({isFirstCommit: ow.boolean}), ow.number, ow.boolean]));
}, 'Expected property `3` to be of type `number` but received type `undefined` in array');

t.throws(() => {
ow(['🦄', {isFirstCommit: true}, 'nope', 5, {accepted: false}], ow.array.exactShape([ow.string, ow.object.exactShape({isFirstCommit: ow.boolean}), ow.string]));
}, 'Did not expect property `3` to exist, got `5` in array');
Copy link
Owner

@sindresorhus sindresorhus Dec 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message is sub-optimal. It should talk about array elements, not properties.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added isArray as an option in exact method declaration to be able to change error message

});