Skip to content

Type guards are not working properly in Observable #19334

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

Closed
aminpaks opened this issue Oct 19, 2017 · 9 comments
Closed

Type guards are not working properly in Observable #19334

aminpaks opened this issue Oct 19, 2017 · 9 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@aminpaks
Copy link
Contributor

aminpaks commented Oct 19, 2017

TypeScript Version: 2.5.3

Code

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/filter';

type AType = 'first' | 'second';

function isFirst(value: AType): value is 'first' {
  return value === 'first';
}

const inputs: AType[] = ['first', 'second'];
const obx = Observable.from(inputs);

obx
  .filter(item => isFirst(item)) // <- checking types with guard
  .subscribe(item => console.log(item)); // <- here item is still `'first' | 'second'`!

A simple example to reproduce.

Expected behavior:
Type guards must make sure the flow continues according to the current status of types.

Actual behavior:
Apparently because the type guard is not within a branch it is not working as intended, or it is working as intended by design that I personally think is not a good idea.

@ghost
Copy link

ghost commented Oct 19, 2017

I think this could be done by updating the rxjs types. If filter is just declared to take (item: T) => boolean then TypeScript won't know that it's a filter and can't be smart, but it could be declared to take (item: T) => T is S just like [].filter is:

// from lib.es5.d.ts
filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];

What version of rxjs are you using? Observable.from and .filter don't seem to be in 5.5.0 or 6.6.0-alpha.0.

@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Oct 19, 2017
@aminpaks
Copy link
Contributor Author

@Andy-MS I'm using [email protected], and tried with 5.5.0 but no difference!
from rxjs:

import { Observable } from '../Observable';
export declare function filter<T, S extends T>(this: Observable<T>, predicate: (value: T, index: number) => value is S, thisArg?: any): Observable<S>;
export declare function filter<T>(this: Observable<T>, predicate: (value: T, index: number) => boolean, thisArg?: any): Observable<T>;

@aminpaks
Copy link
Contributor Author

I found this issue. Is this a duplication?

@ghost
Copy link

ghost commented Oct 20, 2017

Even with 5.4.3 I still can't get your example working:

src/a.ts(11,24): error TS2339: Property 'from' does not exist on type 'typeof Observable'.

And even if I change that line to declare const obx: Observable<any>;, I still can't access a filter method.
Is it possible you have some extension installed?

@aminpaks
Copy link
Contributor Author

@Andy-MS you're missing the from -> import 'rxjs/add/observable/from'

@aminpaks
Copy link
Contributor Author

I updated my question :)

@ghost
Copy link

ghost commented Oct 20, 2017

OK, now the example will work if you replace item => isFirst(item) with isFirst.
We don't infer something as a type predicate unless it's explicitly declared as one (#5101). So item => isFirst(item) just returns a boolean but isFIrst is a type predicate because it was declared as one.

@aminpaks
Copy link
Contributor Author

@Andy-MS that's interesting! Thanks a lot.

@mhegazy
Copy link
Contributor

mhegazy commented Nov 6, 2017

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

2 participants