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

feat(from): make from on non-iterables coerce to iterables #117

Merged
merged 1 commit into from
Oct 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions spec/asynciterable/from-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,26 @@ test('AsyncIterable#from from promise with selector', async t => {
t.end();
});

test('AsyncIterable#from from non-iterable', async t => {
const xs = {};
const res = from(xs);

const it = res[Symbol.asyncIterator]();
await hasNext(t, it, xs);
await noNext(t, it);
t.end();
});

test('AsyncIterable#from from array-like with selector', async t => {
const xs = {};
const res = from(xs, (x, i) => [x, i]);

const it = res[Symbol.asyncIterator]();
await hasNext(t, it, [xs, 0]);
await noNext(t, it);
t.end();
});

interface Observer<T> {
next: (value: T) => void;
error: (err: any) => void;
Expand Down
20 changes: 20 additions & 0 deletions spec/iterable/from-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,23 @@ test('Iterable#from from array-like with selector', t => {
noNext(t, it);
t.end();
});

test('Iterable#from from non-iterable', t => {
const xs = {};
const res = from(xs);

const it = res[Symbol.iterator]();
hasNext(t, it, xs);
noNext(t, it);
t.end();
});

test('Iterable#from from non-iterable with selector', t => {
const xs = {};
const res = from(xs, (x, i) => [x, i]);

const it = res[Symbol.iterator]();
hasNext(t, it, [xs, 0]);
noNext(t, it);
t.end();
});
19 changes: 10 additions & 9 deletions src/asynciterable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import { OperatorAsyncFunction } from './interfaces';
import { bindCallback } from './internal/bindcallback';
import { identityAsync } from './internal/identity';
import { toLength } from './internal/tolength';
import { isIterable, isAsyncIterable } from './internal/isiterable';
import { isArrayLike, isIterable, isAsyncIterable } from './internal/isiterable';
import { Observable } from './observer';
import { AsyncIterable } from './Ix';

/**
* This clas serves as the base for all operations which support [Symbol.asyncIterator].
Expand Down Expand Up @@ -89,14 +88,17 @@ export abstract class AsyncIterableX<T> implements AsyncIterable<T> {
}

const piped = (input: AsyncIterable<T>): AsyncIterableX<R> => {
return operations.reduce((prev: any, fn: OperatorAsyncFunction<T, R>) => fn(prev), input);
return operations.reduce(
(prev: any, fn: OperatorAsyncFunction<T, R>) => fn(prev),
input as any
);
};

return piped(this);
}

static from<TSource, TResult = TSource>(
source: AsyncIterableInput<TSource>,
source: AsyncIterableInput<TSource> | TSource,
selector: (value: TSource, index: number) => TResult | Promise<TResult> = identityAsync,
thisArg?: any
): AsyncIterableX<TResult> {
Expand All @@ -114,8 +116,11 @@ export abstract class AsyncIterableX<T> implements AsyncIterable<T> {
if (isArrayLike(source)) {
return new FromArrayIterable<TSource, TResult>(source, fn);
}
return new FromAsyncIterable<TSource, TResult>(
new OfAsyncIterable<TSource>([source as TSource]),
fn
);
/* tslint:enable */
throw new TypeError('Input type not supported');
}

static of<TSource>(...args: TSource[]): AsyncIterableX<TSource> {
Expand Down Expand Up @@ -270,10 +275,6 @@ function isObservable(x: any): x is Observable<any> {
return x != null && Object(x) === x && typeof x['subscribe'] === 'function';
}

function isArrayLike(x: any): x is ArrayLike<any> {
return x != null && Object(x) === x && typeof x['length'] === 'number';
}

class OfAsyncIterable<TSource> extends AsyncIterableX<TSource> {
private _args: TSource[];

Expand Down
7 changes: 7 additions & 0 deletions src/internal/isiterable.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* @ignore
*/
export function isArrayLike(x: any): x is ArrayLike<any> {
return x != null && Object(x) === x && typeof x['length'] === 'number';
}

/**
* @ignore
*/
Expand Down
20 changes: 14 additions & 6 deletions src/iterable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { OperatorFunction } from './interfaces';
import { bindCallback } from './internal/bindcallback';
import { identity } from './internal/identity';
import { toLength } from './internal/tolength';
import { isIterable } from './internal/isiterable';
import { isArrayLike, isIterable } from './internal/isiterable';

/**
* This clas serves as the base for all operations which support [Symbol.iterator].
Expand Down Expand Up @@ -85,19 +85,27 @@ export abstract class IterableX<T> implements Iterable<T> {
}

const piped = (input: Iterable<T>): IterableX<R> => {
return operations.reduce((prev: any, fn: OperatorFunction<T, R>) => fn(prev), input);
return operations.reduce((prev: any, fn: OperatorFunction<T, R>) => fn(prev), input as any);
};

return piped(this);
}

static from<TSource, TResult = TSource>(
source: Iterable<TSource> | ArrayLike<TSource>,
fn: (value: TSource, index: number) => TResult = identity,
source: Iterable<TSource> | ArrayLike<TSource> | TSource,
selector: (value: TSource, index: number) => TResult = identity,
thisArg?: any
): IterableX<TResult> {
//tslint:disable-next-line
return new FromIterable<TSource, TResult>(source, bindCallback(fn, thisArg, 2));
const fn = bindCallback(selector, thisArg, 2);
/* tslint:disable */
if (isIterable(source)) {
return new FromIterable<TSource, TResult>(source, fn);
}
if (isArrayLike(source)) {
return new FromIterable<TSource, TResult>(source, fn);
}
return new FromIterable<TSource, TResult>(new OfIterable<TSource>([source as TSource]), fn);
/* tslint:enable */
}

static of<TSource>(...args: TSource[]): IterableX<TSource> {
Expand Down