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

Array/Observable filter does not infer chained type #19640

Closed
topaxi opened this issue Nov 1, 2017 · 9 comments
Closed

Array/Observable filter does not infer chained type #19640

topaxi opened this issue Nov 1, 2017 · 9 comments
Labels
Duplicate An existing issue was already created Fixed A PR has been merged for this issue

Comments

@topaxi
Copy link

topaxi commented Nov 1, 2017

TypeScript Version: 2.6.1 using strict: true

Code

[true, true, false, null]
  .filter(thing => thing !== null)
  .map(thing => thing.toString())

Expected behavior:

Compiles

Actual behavior:

3 col 17 error| 2531[QF available]: Object is possibly 'null'.
@ghost
Copy link

ghost commented Nov 1, 2017

Looks like a duplicate of #5101.
A workaround would be to write .filter<boolean>((thing): thing is boolean => thing !== null) that tells us that the expression is a type guard.
Another workaround that I've found useful is to write a mapDefined helper:

function mapDefined<T, U>(iter: Iterable<T>, mapFn: (x: T) => U | undefined): U[] {
    const out: U[] = [];
    for (const x of iter) {
        const res = mapFn(x);
        if (res) {
            out.push(res);
        }
    }
    return out;
}

mapDefined([true, true, false, null], thing => thing === null ? undefined : thing.toString());

EDIT: The .filter won't work without an explicit type argument. This is fixed by #17600.

@topaxi
Copy link
Author

topaxi commented Nov 1, 2017

I noticed this by a different case actually, probably should have posted that one.

['foo', 'bar', null]
  .filter(Boolean)
  .map(s => s.toUpperCase());

This worked with TS ~2.3 and is not working anymore with TS ~2.6. I thought the above would be a simpler reproduction but it seems it is something completely different :) Thanks for your hint though, this helps but still required quite a few new guards in our codebase which worked in a previous TS version 😕

@ghost
Copy link

ghost commented Nov 1, 2017

I just tried that with typescript@2.3 and it doesn't seem to work? I don't think Boolean has ever been considered a type predicate.

@topaxi
Copy link
Author

topaxi commented Nov 1, 2017

You're right doesn't work on arrays, we do have some rxjs observables where this works though, no idea what exactly is different there or if it's project specific.. I will report back later this week.

@mhegazy mhegazy added the Duplicate An existing issue was already created label Nov 1, 2017
@typescript-bot
Copy link
Collaborator

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

@wclr
Copy link

wclr commented Jan 17, 2018

Not sure why this not working:

const list: (string | null)[] = ['A', null, 'C']

list.filter<string>((_) => _ !== null).map(x => x.)

image

Tried latest dev 2.7 still not working and not inferring

@mhegazy
Copy link
Contributor

mhegazy commented Jan 17, 2018

A user-defined type guard is not inferred automatically, a type annotation is expected. i.e.:

const list: (string | null)[] = ['A', null, 'C']

function isNotNull<T>(a: T | null): a is T { return a !== null; }

list.filter(isNotNull).map(x => x.)

@wclr
Copy link

wclr commented Jan 17, 2018

A user-defined type guard is not inferred automatically, a type annotation is expected. i.e.:

It is good to hear, but still complicated, not clear whey it not possible to have auto inference here.

@ghost
Copy link

ghost commented Jan 17, 2018

@whitecolor See #5101

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants