Skip to content

Narrow to Exclude type in conditional code #29280

Closed
@ranma42

Description

@ranma42

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions