-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Loss of empty type constraint in generics #36124
Comments
Well, the following things are taken to be true when evaluating type arguments and constraints:
The first two are inarguable. The last one is... not that much of a stretch, and was actually correct before the introduction of Now that that particular cat is out of the bag, I doubt it can be put back without incurring a ton of breaking changes that wouldn't really materially benefit anyone. Inconsistencies are not per se defects so I don't think there's anything actionable here. |
It took me several parses and several response drafts to this, but I think I finally have it. @RyanCavanaugh maybe you would oblige by checking my inference/understanding here. Essentially: There is a contradiction between the treatment of unconstrained generic type parameters and the relationship between For me come to this conclustion, I assumed that an unconstrained generic parameter can be re-written with an explicit constraint [if it isn't actually possible to do this, the whole premise breaks down], that is: type SomeType<T> = ... // doesn't matter is identical, for some type SomeType<T extends DefaultConstraintType> = ... // doesn't matter To elucidate the type of
One can try this graphically, there's no way to draw a Venn diagram where all of these constraints can be satisfied. Therefore, given the current treatment of unconstrained generic parameter types, the relationship between So, it's a bug as long as one expects a well-defined relationship between As for my original intention of using type Concrete = number | string | boolean | symbol | object; [Addendum]: I wonder -- if we wanted to go for consistency and drop one of the three constraints I've drawn out -- which one would be least harmful as a breaking change?. [Addendum-dum]: I guess this status quo would not cause a bug as long as one doesn't have a program where one not rely on interaction between |
This appears to be fixed somewhere between 4.7.4 and 4.8.4 |
Indeed, thanks |
TypeScript Version: 3.8.0-dev.20200109
Search Terms:
generic, empty type, lost constraint
Code
Expected behavior/Actual behavior:
As annotated in the example.`
To expand,
AlsoMustNotBeNull
has no explicit constraint onT
, whereasMustNotBeNull
has an{}
constraint on itsT
, so the former shouldn't fit the latter.That this alias definition is allowed suggests that the fallback constraint is also
{}
(which I thought wasn't the case). And even if there was such a fallback constraint of{}
, I would have expectedAlsoMustNotBeNull<null>
not to be a valid type.An alternative inference would be that there is a bug in
type AlsoMustNotBeNull<T> = MustNotBeNull<T>
, and the left hand side should really have been likewise constrained toextends {}
.Playground Link:
https://www.typescriptlang.org/play/?ts=3.8.0-dev.20200109&ssl=1&ssc=1&pln=9&pc=43#code/G4QwTgBAxiB2sHsAuAhApgOQK4BscC4IBvAXwgF4JZccIB6OiAFQE8AHNCAUTDATAB0EAFAMIAcQCWwNLAhIAFpxAAjBDIgq0CkMEn8ICAGZUaVZJrSTYAc2gJYAZ0kATNGDQuIICI6wqkdk5jYhIBcOFhQI4IAFksRyQMZHRsPAAeJgg0AA8kWRdHUIA+CmYAbmEoB0SIIwQEQnjE5NRMGnTqPFLKLpxy+kZWGJ4+MFFGcIE4L0VJItV1TgAKRwQ68HsnefzYJABKSx09finI6M4AQRw15qSU9oymHriE+7a0nEzSsSnFWQANPIFPNfAoELgXLAAORISzePAIADuniBKiwcMkmMcAEIqjU4SpwIRrrc3q1Uh0+i8+uUgA
Discussion
Just to give some context, I wanted to add a simple generic constraint that would essentially forbid "nullish" type, which led to my discovering that
null
cannot fit into{}
.I see that #7648 has a good discussion on expressing non-nullish type as a stand alone type, but not as a type constraint. Regardless of the discussion there, however, in my understanding so far the above example is still an unexpected behavior, because the constraint that forbids
null
in one generic is lost when being aliased by another generic.The text was updated successfully, but these errors were encountered: