Skip to content

Commit

Permalink
Add method to return the error without throwing sindresorhus#169
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus authored and aqzhyi committed Mar 7, 2020
1 parent b2285d0 commit bc879c1
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 0 deletions.
24 changes: 24 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,30 @@ checkPassword('foo');
//=> ArgumentError: Expected string `password` to have a minimum length of `6`, got `foo`
```

### ow.validate(predicate)

Create a reusable validator. It returns error and value.

```ts
const checkPassword = ow.validate(ow.string.minLength(6));

const password = 'foo';

const {error, value} = checkPassword(password);
//=> ArgumentError: Expected string `password` to have a minimum length of `6`, got `foo`
```

### ow.createValidate(label, predicate)

Create a reusable validator with a specific `label`. It returns error and value.

```ts
const checkPassword = ow.createValidate('password', ow.string.minLength(6));

const {error, value} = checkPassword('foo');
//=> ArgumentError: Expected string `password` to have a minimum length of `6`, got `foo`
```

### ow.any(...predicate[])

Returns a predicate that verifies if the value matches at least one of the given predicates.
Expand Down
66 changes: 66 additions & 0 deletions source/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,38 @@ export interface Ow extends Modifiers, Predicates {
@param predicate - Predicate used in the validator function.
*/
create<T>(label: string, predicate: BasePredicate<T>): ReusableValidator<T>;

/**
Test if the value matches the predicate. It returns error and value.
@param value - Value to test.
@param predicate - Predicate to test against.
*/
validate<T>(value: T, predicate: BasePredicate<T>): {error: Error | null; value: T};

/**
Test if the value matches the predicate. It returns error and value.
@param value - Value to test.
@param label - Label which should be used in error messages.
@param predicate - Predicate to test against.
*/
validate<T>(value: T, label: string, predicate: BasePredicate<T>): {error: Error | null; value: T};

/**
Create a reusable validator. It returns error, It ReusableValidator returns error.
@param predicate - Predicate to test against.
*/
createValidate<T>(predicate: BasePredicate<T>): (value: T, label?: string) => {error: Error | null; value: T};

/**
Create a reusable validator. It returns error, It ReusableValidator returns error.
@param label - Label which should be used in error messages.
@param predicate - Predicate to test against.
*/
createValidate<T>(label: string, predicate: BasePredicate<T>): (value: T, label?: string) => {error: Error | null; value: T};
}

/**
Expand Down Expand Up @@ -108,6 +140,40 @@ Object.defineProperties(ow, {

test(value, label ?? (labelOrPredicate as string), predicate as BasePredicate<T>);
}
},
validate: {
value: <T>(value: T, labelOrPredicate: unknown, predicate?: BasePredicate<T>) => {
try {
ow(value, labelOrPredicate, predicate);

return {
error: null,
value
};
} catch (error) {
return {
error,
value
};
}
}
},
createValidate: {
value: <T>(labelOrPredicate: BasePredicate<T> | string | undefined, predicate?: BasePredicate<T>) => (value: T, label?: string) => {
try {
ow(value, label ?? labelOrPredicate, predicate);

return {
error: null,
value
};
} catch (error) {
return {
error,
value
};
}
}
}
});

Expand Down
41 changes: 41 additions & 0 deletions test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,37 @@ test('isValid', t => {
t.false(ow.isValid(true as any, ow.any(ow.string, ow.number)));
});

test('validate', t => {
const valueCauseError = 1 as any as string;

t.notThrows(() => {
const {error, value} = ow.validate('foo', ow.string);
t.true(error === null);
t.true(value === 'foo');
});

t.notThrows(() => {
const {error, value} = ow.validate('foo', 'label', ow.string);
t.true(error === null);
t.true(value === 'foo');
});

t.notThrows(() => {
const {error, value} = ow.validate(valueCauseError, ow.string);
t.true(error instanceof Error);
t.true(value === valueCauseError);
});

t.notThrows(() => {
const {error, value} = ow.validate(valueCauseError, 'label', ow.string);
t.true(error instanceof Error);
t.true(value === valueCauseError);
});
});

test('reusable validator', t => {
const checkUsername = ow.create(ow.string.minLength(3));
const checkNickname = ow.createValidate('nickname', ow.string.minLength(3));

const value = 'x';

Expand All @@ -303,6 +332,18 @@ test('reusable validator', t => {
t.throws(() => {
checkUsername(5 as any);
}, 'Expected argument to be of type `string` but received type `number`');

t.notThrows(() => {
const {error, value} = checkNickname('foo');
t.true(error === null);
t.true(value === 'foo');
});

t.notThrows(() => {
const {error, value} = checkNickname('fo');
t.true(error instanceof Error);
t.true(value === 'fo');
});
});

test('reusable validator called with label', t => {
Expand Down

0 comments on commit bc879c1

Please sign in to comment.