rxjs: Observable.from(iterable) generates Typescript compiler error

RxJS version: 5.0.3

Code to reproduce:

function* generateDoubles(seed: number) {
  let i = seed;
  while (true) {
    yield i;
    i = 2 * i; // double it
  }
}

const iterator = generateDoubles(3);
const result = Rx.Observable.from<number>(iterator).take(10);
result.subscribe((x: number) => console.log(x));

Expected behavior: Since this is the example given on reactivex.io It would be expected to compile in Typescript without an error.

Actual behavior:

error TS2345: Argument of type 'IterableIterator<number>' is not assignable to parameter of type 'ObservableInput<number>'.
  Type 'IterableIterator<number>' is not assignable to type 'PromiseLike<number>'.
    Property 'then' is missing in type 'IterableIterator<number>'.

Additional information: This seems to be an issue with the definition of ObservableInput<T>:

export interface Subscribable<T> {
    subscribe(observerOrNext?: PartialObserver<T> | ((value: T) => void), error?: (error: any) => void, complete?: () => void): AnonymousSubscription;
}
export declare type SubscribableOrPromise<T> = Subscribable<T> | PromiseLike<T>;
export declare type ObservableInput<T> = SubscribableOrPromise<T> | ArrayLike<T>;

The iterable type is missing.

A fix might be to add:

export interface IterableLike<T> {
    [Symbol.iterator](): Iterator<T> | IterableIterator<T>;
}

// and fix ObservableInput<T>
export declare type ObservableInput<T> = SubscribableOrPromise<T> | ArrayLike<T> | IterableLike<T>;

tsconfig.json

{
	"compilerOptions": {
		"target": "es2015",
		"module": "commonjs",
		"moduleResolution": "node",
		"sourceMap": true,
		"alwaysStrict": true,
        "declaration": true,
		"noImplicitAny": true,
		"noImplicitThis": true,
		"strictNullChecks": true,
		"outDir": "dist",
		"lib": ["dom", "dom.iterable", "es2015", "es2015.iterable", "scripthost"]
	},
	"include": [
		"src"
	]
}

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 5
  • Comments: 25 (11 by maintainers)

Most upvoted comments

What’s the current status on this issue? It’s really a bummer having to cast back to <any>. Is there any interest in adding a fromIterable() operator? Is there any better way to resolve this now that we’re up to TypeScript 2.4? @david-driscoll @felixfbecker

Now that we have Iterable<T> used elsewhere in the code base, and the fact that TypeScript with iterables have been out for a while, I think we can add Iterable<T> to ObservableInput<T> and then this problem goes away.

We can augment interfaces, but it doesn’t appear there is any way to augment type unions. Which kind of makes sense with how augmentation works, it’s kind of crappy though.

We had Iterable<T> in there, during the early days, but we removed it because of problems with users that don’t have it enabled at the compiler level. This was before the compiler could choose a custom combination of libs (which came with 2.0 iirc). See #1582 for the code that removed it.

Now that we have lib:[] we might be able to bring it back.

Risks involve:

  • Anyone that wants to use RxJS must turn on es2015.iterable
  • If they don’t target ES6 (perhaps ES5, needs testing) they will get weird runtime errors if they attempt to use Iterable.

Ts2.2 is bringing in downlevel support for generators to ES3, via https://github.com/Microsoft/TypeScript/pull/12346 . So once we get to TS 2.2 this seems like an appropriate change, until then I’m not really sure.

I’m wondering if we should just throw our hands up with from and pass any to it. The type checking here is pretty painful, and then we have to check at run time anyhow.