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

Aliased Conditions with explicit type definition results in the "old" behavior #45469

Open
WGroenestein opened this issue Aug 16, 2021 · 4 comments
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@WGroenestein
Copy link

Bug Report

πŸ”Ž Search Terms

Aliased Conditions

πŸ•— Version & Regression Information

V4.4.0-beta / nightly

  • I was unable to test this on prior versions because it is a new feature

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

type Shape =
    | { kind: "circle", radius: number }
    | { kind: "square", sideLength: number };

function area(shape: Shape): number {
    const isCircle: boolean = shape.kind === "circle";
    if (isCircle) {
        // We know we have a circle here!
        return Math.PI * shape.radius ** 2;
    }
    else {
        // We know we're left with a square here!
        return shape.sideLength ** 2;
    }
}

πŸ™ Actual behavior

Adding the explicit type to "isCircle" results in that the sample breaks

Property 'radius' does not exist on type 'Shape'.
  Property 'radius' does not exist on type '{ kind: "square"; sideLength: number; }'.
Property 'sideLength' does not exist on type 'Shape'.
  Property 'sideLength' does not exist on type '{ kind: "circle"; radius: number; }'.

πŸ™‚ Expected behavior

Making the implicit type explicit, does not result in the behavior to change.

Using the sample provided by the TS 4.4 RC announcement, getting the implicit type of "isCircle" (by hovering over it) yields boolean
image
. By then explicitly defining the type (boolean), the Aliased Conditions seems to break/revert back to pre 4.4 behavior.

@IllusionMH
Copy link
Contributor

This is mentioned explicitly in PR that implements feature (#44730 after first code block):

Narrowing through indirect references occurs only when the conditional expression or discriminant property access is declared in a const variable declaration with no type annotation, and ...

@WGroenestein
Copy link
Author

Thanks for pointing out that indeed it seems to be by design according to the PR, and there is probably a good technical reason for why it is like that. However I would argue that from a functional (the consuming developer) perspective it is unexpected (and even inconsistent) behavior. I.e. a type which is determined by the compiler (i.e. the boolean presented to the developer) and a type annotation of that same type, is in my opinion expected to behave identical.

Imaging the following scenario:
Your team has the coding style to use explicit types for everything (e.g. for readability and code review purposes)

  • you can not utilize this new feature (boo)
  • you need to make an exception for this very specific use case so you can still use this new awesome feature (yeah). Then a team member comes along and makes a trivial code improvement (adding the missing explicit type) and ends up with a compilation error (and most likely be flabbergasted with what just happened)

If I recall correctly at some point (and maybe even still today) it was even suggested to use explicit type annotations as a way to speed up the TS compilation process. And if that recollection is correct, it would mean that we now have conflicting rules for the usage of the TypeScript language.

What would be the best way forward? Should I close this bug and create a new issue with a feature request to enable this new awesome feature even when an explicit type annotation is present on the const?

@DanielRosenwasser DanielRosenwasser added In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels Aug 18, 2021
@DanielRosenwasser
Copy link
Member

I can't necessarily comment on the original rationale; however, the current behavior allows users to "opt out" of using a condition for narrowing, and gives us room for some different sort of annotation in the future to signal "this is a boolean, and you should interpret the condition here".

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Aug 18, 2021

Perhaps something like const isCircle: shape is Circle, like how type predicate signatures use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants