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

Narrow to Exclude type in conditional code #29280

Closed
4 of 5 tasks
ranma42 opened this issue Jan 6, 2019 · 8 comments
Closed
4 of 5 tasks

Narrow to Exclude type in conditional code #29280

ranma42 opened this issue Jan 6, 2019 · 8 comments
Labels
Duplicate An existing issue was already created

Comments

@ranma42
Copy link

ranma42 commented Jan 6, 2019

Search Terms

conditional else exclude narrow

Suggestion

TypeScript should infer Exclude types in conditional expressions and statements.
Specifically, whenever the positive branch (if, or the x in c ? x : y) has a more specific type thanks to a type guard, the negative branch (else/y) should have the relevant Exclude type.

Use Cases

This would provide a natural way to infer Exclude types and it would generalise in a natural way the current behaviour of conditional statements over union and finite-domain types.
Apparently right now the only way to have a value of type Exclude is to assert it manually (either through type guards or type assertions).

Examples

function partition<A, B extends A>(items: A[], f: (x: A) => x is B): [B[], Array<Exclude<A, B>>] {
    const bs: B[] = [];
    const others: Array<Exclude<A, B>> = [];
    for (const x of items) {
        if (f(x)) {
            bs.push(x);
        } else { // with the proposed feature, x: Exclude<A, B> in this branch
            others.push(x); // while currently this fails because TSC infers x: A
        }
    }
    return [bs, others];
}

Playground link

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behaviour of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

I am unsure if this could break existing code.
Making the typing more accurate could reveal dead code, which could result in compilation errors.

@ajafff
Copy link
Contributor

ajafff commented Jan 6, 2019

This should be covered by #22348

@ranma42
Copy link
Author

ranma42 commented Jan 6, 2019

Possibly a duplicate of #23764

@ranma42
Copy link
Author

ranma42 commented Jan 7, 2019

Notice that this is consistent with the fact that the positive branch infers the Extract type (already resolved to the non-never type, thanks to the constraints on type guards).

@weswigham weswigham added the Duplicate An existing issue was already created label Jan 7, 2019
@weswigham
Copy link
Member

#22348 would be what this needs, yeah. Conditional types still have a few problems that make the current behavior by-design, though 😦

@ranma42
Copy link
Author

ranma42 commented Jan 8, 2019

I built #22348 locally and the example above fails to compile with the same error:
error TS2345: Argument of type 'A' is not assignable to parameter of type 'Exclude<A, B>'.

@weswigham
Copy link
Member

PR isn't quite fully done (it has issues as-is). It doesn't swap control flow to using extract/exclude yet afaik.

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@ranma42
Copy link
Author

ranma42 commented Jan 11, 2019

This issue is likely a duplicate of #23764, but while that was a bug report (and thus closed as "not a bug"), this is a feature request, proposing an improvement to type narrowing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants