From 291117047b8484ef5d36a9089bc4105f0eee2bde Mon Sep 17 00:00:00 2001 From: sdotson Date: Thu, 6 Jan 2022 10:44:29 -0500 Subject: [PATCH] fix is.iterable and add is.iterableiterator --- source/index.ts | 8 +++++-- test/test.ts | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/source/index.ts b/source/index.ts index 86499f1..26ab397 100644 --- a/source/index.ts +++ b/source/index.ts @@ -181,11 +181,12 @@ is.buffer = (value: unknown): value is Buffer => (value as any)?.constructor?.is is.nullOrUndefined = (value: unknown): value is null | undefined => is.null_(value) || is.undefined(value); is.object = (value: unknown): value is object => !is.null_(value) && (typeof value === 'object' || is.function_(value)); -is.iterable = (value: unknown): value is IterableIterator => is.function_((value as IterableIterator)?.[Symbol.iterator]); +is.iterable = (value: unknown): value is Iterable => is.function_((value as Iterable)?.[Symbol.iterator]); +is.iterableIterator = (value: unknown): value is IterableIterator => is.iterable(value) && is.function_((value as IterableIterator)?.next) && is.any([is.function_, is.undefined], (value as IterableIterator)?.throw) && is.any([is.function_, is.undefined], (value as IterableIterator)?.return); is.asyncIterable = (value: unknown): value is AsyncIterableIterator => is.function_((value as AsyncIterableIterator)?.[Symbol.asyncIterator]); -is.generator = (value: unknown): value is Generator => is.iterable(value) && is.function_(value.next) && is.function_(value.throw); +is.generator = (value: unknown): value is Generator => is.iterable(value) && is.function_((value as Generator)?.next) && is.function_((value as Generator)?.throw); is.asyncGenerator = (value: unknown): value is AsyncGenerator => is.asyncIterable(value) && is.function_(value.next) && is.function_(value.throw); @@ -413,6 +414,7 @@ export const enum AssertionTypeDescription { numericString = 'string with a number', nullOrUndefined = 'null or undefined', iterable = 'Iterable', + iterableIterator = 'Iterable Iterator', asyncIterable = 'AsyncIterable', nativePromise = 'native Promise', urlString = 'string with a URL', @@ -469,6 +471,7 @@ interface Assert { nullOrUndefined: (value: unknown) => asserts value is null | undefined; object: (value: unknown) => asserts value is Record; iterable: (value: unknown) => asserts value is Iterable; + iterableIterator: (value: unknown) => asserts value is IterableIterator; asyncIterable: (value: unknown) => asserts value is AsyncIterable; generator: (value: unknown) => asserts value is Generator; asyncGenerator: (value: unknown) => asserts value is AsyncGenerator; @@ -569,6 +572,7 @@ export const assert: Assert = { 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), iterable: (value: unknown): asserts value is Iterable => assertType(is.iterable(value), AssertionTypeDescription.iterable, value), + iterableIterator: (value: unknown): asserts value is IterableIterator => assertType(is.iterableIterator(value), AssertionTypeDescription.iterableIterator, value), asyncIterable: (value: unknown): asserts value is AsyncIterable => assertType(is.asyncIterable(value), AssertionTypeDescription.asyncIterable, value), generator: (value: unknown): asserts value is Generator => assertType(is.generator(value), 'Generator', value), asyncGenerator: (value: unknown): asserts value is AsyncGenerator => assertType(is.asyncGenerator(value), 'AsyncGenerator', value), diff --git a/test/test.ts b/test/test.ts index 87455db..d6f94a2 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1069,6 +1069,66 @@ test('is.iterable', t => { }); }); +test('is.iterableIterator', t => { + t.true(is.iterableIterator({ + [Symbol.iterator]: () => ({[Symbol.iterator]: () => {}}), + next: () => {}, + throws: () => {}, + returns: () => {} + })); + t.true(is.iterableIterator({ + [Symbol.iterator]: () => ({[Symbol.iterator]: () => {}}), + next: () => {}, + throws: undefined, + returns: undefined + })); + t.false(is.iterableIterator(new Map())); + t.false(is.iterableIterator([])); + t.false(is.iterableIterator('')); + t.false(is.iterableIterator(null)); + t.false(is.iterableIterator(undefined)); + t.false(is.iterableIterator(0)); + t.false(is.iterableIterator(NaN)); + t.false(is.iterableIterator(Infinity)); + t.false(is.iterableIterator({})); + + t.notThrows(() => { + assert.iterableIterator({ + [Symbol.iterator]: () => ({[Symbol.iterator]: () => {}}), + next: () => {}, + throws: () => {}, + returns: () => {} + }); + }); + t.throws(() => { + assert.iterableIterator(''); + }); + t.throws(() => { + assert.iterableIterator([]); + }); + t.throws(() => { + assert.iterableIterator(new Map()); + }); + t.throws(() => { + assert.iterableIterator(null); + }); + t.throws(() => { + assert.iterableIterator(undefined); + }); + t.throws(() => { + assert.iterableIterator(0); + }); + t.throws(() => { + assert.iterableIterator(NaN); + }); + t.throws(() => { + assert.iterableIterator(Infinity); + }); + t.throws(() => { + assert.iterableIterator({}); + }); +}); + test('is.asyncIterable', t => { t.true(is.asyncIterable({ [Symbol.asyncIterator]: () => {}