Skip to content

Inconsistent property type deduction with type guard. #53453

@quangloc99

Description

@quangloc99

Bug Report

I created this issue to reopen #53313. It was marked as Not a defect, but there are follow-up questions from me that are unanswered. I still believe both cases described below should have the same behavior.

🔎 Search Terms

type guard, control flow analysis

🕗 Version & Regression Information

  • This changed between versions 4.9.5 and 5.0.2

⏯ Playground Link

Playground link with relevant code

💻 Code

type If<Condition extends boolean, TrueType, FalseType = undefined> = Condition extends true
    ? TrueType
    : Condition extends false
    ? FalseType
    : TrueType | FalseType;

type X<T extends boolean = boolean> = {
  x: If<T, number>;
}

// Failed example
{
  function hasDefinedField(o: X): o is X<true> {
    return o.x !== undefined;
  }

  function doStuff(o: X): number {
    if (hasDefinedField(o)) {
      return o.x;  // <--- Failed to deduce the type
    }
    return 0;
  }
}

// Working example
{
  type A = X<true>;   // Magic alias
  function hasDefinedField(o: X): o is A {
    return o.x !== undefined;
  }

  function doStuff(o: X): number {
    if (hasDefinedField(o)) {
      return o.x;  // <--- Type is now _correct_
    }
    return 0;
  }
}

🙁 Actual behavior

The Failed example failed at deducing its property, while in the Working example, only by aliasing type A = X<true>, the error is gone.

🙂 Expected behavior

Both examples should have the same behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions