parent
c68ad76062
commit
1f2440ae0d
3 changed files with 76 additions and 0 deletions
32
readme.md
32
readme.md
|
|
@ -587,6 +587,21 @@ is.all(is.string, '🦄', [], 'unicorns');
|
|||
//=> false
|
||||
```
|
||||
|
||||
##### .optional(value, predicate)
|
||||
|
||||
Returns `true` if `value` is `undefined` or satisfies the given `predicate`.
|
||||
|
||||
```js
|
||||
is.optional(undefined, is.string);
|
||||
//=> true
|
||||
|
||||
is.optional('🦄', is.string);
|
||||
//=> true
|
||||
|
||||
is.optional(123, is.string);
|
||||
//=> false
|
||||
```
|
||||
|
||||
##### .validDate(value)
|
||||
|
||||
Returns `true` if the value is a valid date.
|
||||
|
|
@ -682,6 +697,23 @@ handleMovieRatingApiResponse({rating: 0.87, title: 'The Matrix'});
|
|||
handleMovieRatingApiResponse({rating: '🦄'});
|
||||
```
|
||||
|
||||
### Optional assertion
|
||||
|
||||
Asserts that `value` is `undefined` or satisfies the provided `assertion`.
|
||||
|
||||
```ts
|
||||
import {assert} from '@sindresorhus/is';
|
||||
|
||||
assert.optional(undefined, assert.string);
|
||||
// Passes without throwing
|
||||
|
||||
assert.optional('🦄', assert.string);
|
||||
// Passes without throwing
|
||||
|
||||
assert.optional(123, assert.string);
|
||||
// Throws: Expected value which is `string`, received value of type `number`
|
||||
```
|
||||
|
||||
## Generic type parameters
|
||||
|
||||
The type guards and type assertions are aware of [generic type parameters](https://www.typescriptlang.org/docs/handbook/generics.html), such as `Promise<T>` and `Map<Key, Value>`. The default is `unknown` for most cases, since `is` cannot check them at runtime. If the generic type is known at compile-time, either implicitly (inferred) or explicitly (provided), `is` propagates the type so it can be used later.
|
||||
|
|
|
|||
|
|
@ -318,6 +318,7 @@ const is = Object.assign(
|
|||
urlInstance: isUrlInstance,
|
||||
urlSearchParams: isUrlSearchParams,
|
||||
urlString: isUrlString,
|
||||
optional: isOptional,
|
||||
validDate: isValidDate,
|
||||
validLength: isValidLength,
|
||||
weakMap: isWeakMap,
|
||||
|
|
@ -342,6 +343,10 @@ export function isAny(predicate: Predicate | Predicate[], ...values: unknown[]):
|
|||
);
|
||||
}
|
||||
|
||||
export function isOptional<T>(value: unknown, predicate: (value: unknown) => value is T): value is T | undefined {
|
||||
return isUndefined(value) || predicate(value);
|
||||
}
|
||||
|
||||
export function isArray<T = unknown>(value: unknown, assertion?: (value: T) => value is T): value is T[] {
|
||||
if (!Array.isArray(value)) {
|
||||
return false;
|
||||
|
|
@ -940,11 +945,19 @@ type Assert = {
|
|||
// Variadic functions.
|
||||
any: (predicate: Predicate | Predicate[], ...values: unknown[]) => void | never;
|
||||
all: (predicate: Predicate, ...values: unknown[]) => void | never;
|
||||
|
||||
/**
|
||||
Asserts that `value` is `undefined` or satisfies the provided `assertion`.
|
||||
|
||||
Useful for optional inputs.
|
||||
*/
|
||||
optional: <T>(value: unknown, assertion: (value: unknown, message?: string) => asserts value is T, message?: string) => asserts value is T | undefined;
|
||||
};
|
||||
|
||||
export const assert: Assert = {
|
||||
all: assertAll,
|
||||
any: assertAny,
|
||||
optional: assertOptional,
|
||||
array: assertArray,
|
||||
arrayBuffer: assertArrayBuffer,
|
||||
arrayLike: assertArrayLike,
|
||||
|
|
@ -1148,6 +1161,12 @@ export function assertAny(predicate: Predicate | Predicate[], ...values: unknown
|
|||
}
|
||||
}
|
||||
|
||||
export function assertOptional<T>(value: unknown, assertion: (value: unknown, message?: string) => asserts value is T, message?: string): asserts value is T | undefined {
|
||||
if (!isUndefined(value)) {
|
||||
assertion(value, message);
|
||||
}
|
||||
}
|
||||
|
||||
export function assertArray<T = unknown>(value: unknown, assertion?: (element: unknown, message?: string) => asserts element is T, message?: string): asserts value is T[] {
|
||||
if (!isArray(value)) {
|
||||
throw new TypeError(message ?? typeErrorMessage('Array', value));
|
||||
|
|
|
|||
25
test/test.ts
25
test/test.ts
|
|
@ -2251,3 +2251,28 @@ test('custom assertion message', t => {
|
|||
assert.whitespaceString(undefined, message);
|
||||
}, {instanceOf: TypeError, message});
|
||||
});
|
||||
|
||||
test('is.optional', t => {
|
||||
t.true(is.optional(undefined, is.string));
|
||||
t.true(is.optional('🦄', is.string));
|
||||
t.false(is.optional(123, is.string));
|
||||
t.false(is.optional(null, is.string));
|
||||
});
|
||||
|
||||
test('assert.optional', t => {
|
||||
t.notThrows(() => {
|
||||
assert.optional(undefined, assert.string);
|
||||
});
|
||||
|
||||
t.notThrows(() => {
|
||||
assert.optional('🦄', assert.string);
|
||||
});
|
||||
|
||||
t.throws(() => {
|
||||
assert.optional(123, assert.string);
|
||||
});
|
||||
|
||||
t.throws(() => {
|
||||
assert.optional(null, assert.string);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue