From 3f93bf200d48aa447ae3b6c5b7271ead4d0f552a Mon Sep 17 00:00:00 2001 From: Arnovsky Date: Sat, 25 Jul 2020 10:11:59 +0300 Subject: [PATCH] Add `is.array` overload that supports asserting array items (#119) Co-authored-by: Pedro Augusto de Paula Barbosa Co-authored-by: Giora Guttsait Co-authored-by: Sindre Sorhus --- readme.md | 10 +++++++++- source/index.ts | 24 +++++++++++++++++++++--- test/test.ts | 24 ++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 98e29ca..daddc0a 100644 --- a/readme.md +++ b/readme.md @@ -93,7 +93,15 @@ Note: `is.number(NaN)` returns `false`. This intentionally deviates from `typeof #### Built-in types -##### .array(value) +##### .array(value, assertion?) + +Returns true if `value` is an array and all of its items match the assertion (if provided). + +```js +is.array(value); // Validate `value` is an array. +is.array(value, is.number); // Validate `value` is an array and all of its items are numbers. +``` + ##### .function(value) ##### .buffer(value) ##### .object(value) diff --git a/source/index.ts b/source/index.ts index ba578a4..9bed5cc 100644 --- a/source/index.ts +++ b/source/index.ts @@ -165,7 +165,18 @@ is.symbol = isOfType('symbol'); is.numericString = (value: unknown): value is string => is.string(value) && !is.emptyStringOrWhitespace(value) && !Number.isNaN(Number(value)); -is.array = Array.isArray; +is.array = (value: unknown, assertion?: (value: T) => value is T): value is T[] => { + if (!Array.isArray(value)) { + return false; + } + + if (!assertion) { + return true; + } + + return value.every(assertion); +}; + is.buffer = (value: unknown): value is Buffer => (value as any)?.constructor?.isBuffer?.(value) ?? false; is.nullOrUndefined = (value: unknown): value is null | undefined => is.null_(value) || is.undefined(value); @@ -438,7 +449,7 @@ interface Assert { boolean: (value: unknown) => asserts value is boolean; symbol: (value: unknown) => asserts value is symbol; numericString: (value: unknown) => asserts value is string; - array: (value: unknown) => asserts value is T[]; + array: (value: unknown, assertion?: (element: unknown) => asserts element is T) => asserts value is T[]; buffer: (value: unknown) => asserts value is Buffer; nullOrUndefined: (value: unknown) => asserts value is null | undefined; object: (value: unknown) => asserts value is Record; @@ -528,7 +539,14 @@ export const assert: Assert = { boolean: (value: unknown): asserts value is boolean => assertType(is.boolean(value), 'boolean', value), symbol: (value: unknown): asserts value is symbol => assertType(is.symbol(value), 'symbol', value), numericString: (value: unknown): asserts value is string => assertType(is.numericString(value), AssertionTypeDescription.numericString, value), - array: (value: unknown): asserts value is T[] => assertType(is.array(value), 'Array', value), + array: (value: unknown, assertion?: (element: unknown) => asserts element is T): asserts value is T[] => { + const assert: (condition: boolean, description: string, value: unknown) => asserts condition = assertType; + assert(is.array(value), 'Array', value); + + if (assertion) { + value.forEach(assertion); + } + }, buffer: (value: unknown): asserts value is Buffer => assertType(is.buffer(value), 'Buffer', value), nullOrUndefined: (value: unknown): asserts value is null | undefined => assertType(is.nullOrUndefined(value), AssertionTypeDescription.nullOrUndefined, value), object: (value: unknown): asserts value is object => assertType(is.object(value), 'Object', value), diff --git a/test/test.ts b/test/test.ts index 31bfa2a..16e376c 100644 --- a/test/test.ts +++ b/test/test.ts @@ -641,6 +641,30 @@ test('is.numericString', t => { test('is.array', t => { testType(t, 'array', ['emptyArray']); + + t.true(is.array([1, 2, 3], is.number)); + t.false(is.array([1, '2', 3], is.number)); + + t.notThrows(() => { + assert.array([1, 2], assert.number); + }); + + t.throws(() => { + assert.array([1, '2'], assert.number); + }); + + t.notThrows(() => { + const x: unknown[] = [1, 2, 3]; + assert.array(x, assert.number); + x[0].toFixed(0); + }); + + t.notThrows(() => { + const x: unknown[] = [1, 2, 3]; + if (is.array(x, is.number)) { + x[0].toFixed(0); + } + }); }); test('is.function', t => {