-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Reduce intersections by discriminants #36696
Conversation
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the perf test suite on this PR at 94353d2. You can monitor the build here. It should now contribute to this PR's status checks. |
Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at 94353d2. You can monitor the build here. It should now contribute to this PR's status checks. |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at 94353d2. You can monitor the build here. It should now contribute to this PR's status checks. |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 94353d2. You can monitor the build here. It should now contribute to this PR's status checks. |
The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master. |
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the perf test suite on this PR at 346ec30. You can monitor the build here. It should now contribute to this PR's status checks. |
Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at 346ec30. You can monitor the build here. It should now contribute to this PR's status checks. |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at 346ec30. You can monitor the build here. It should now contribute to this PR's status checks. |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 346ec30. You can monitor the build here. It should now contribute to this PR's status checks. |
@typescript-bot run dt |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at acd3fec. You can monitor the build here. It should now contribute to this PR's status checks. |
@typescript-bot run dt |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 3a1ba48. You can monitor the build here. It should now contribute to this PR's status checks. |
@typescript-bot run dt |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 37c6280. You can monitor the build here. It should now contribute to this PR's status checks. |
@typescript-bot perf test this |
Heya @ahejlsberg, I've started to run the perf test suite on this PR at 37c6280. You can monitor the build here. It should now contribute to this PR's status checks. Update: The results are in! |
@ahejlsberg Here they are:Comparison Report - master..36696
System
Hosts
Scenarios
|
Since updating to 3.9 I have a compile error which I suspect is caused by this PR. The error might be valid, but could someone explain to me why? class A {
private _name = "A";
public y: number = 1;
}
class B {
private _name = "B"
public y: number = 2;
}
class C {
public y: number = 3;
}
let c: A & B = new C();
// Error: Type 'C' is not assignable to type 'never'.
// The intersection 'A & B' was reduced to 'never' because property '_name'
// exists in multiple constituents and is private in some.(2322) What I'm not getting is why the private variable would have any say in this? I thought doing something like |
Generate type files for older typescript compilers Fixed issues relating to: microsoft/TypeScript#36696 Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
Generate type files for older typescript compilers Fixed issues relating to: microsoft/TypeScript#36696 Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
Generate type files for older typescript compilers Fixed issues relating to: microsoft/TypeScript#36696 Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
Generate type files for older typescript compilers Fixed issues relating to: microsoft/TypeScript#36696 Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
Generate type files for older typescript compilers Fixed issues relating to: microsoft/TypeScript#36696 Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
@andrewvarga This is a bit of a late comment, but it's because |
When types are checked if they are `never` by their `TypeFlags`, they must first be reduced, because intersection types of object-like types which reduce to `never` don't have `TypeFlags.Never`. See microsoft#36696 for details. When a function is declared to return such type and it doesn't contain any return statement or it only contains return statements without expression, the error messages are incorrect as the checker sees its return type as non-`never`. This commit takes into account that intersection types potentially reduces to `never` and improves error messages.
When types are checked if they are `never` by their `TypeFlags`, they must first be reduced, because intersection types of object-like types which reduce to `never` don't have `TypeFlags.Never`. See microsoft#36696 for details. When a function is declared to return such type and it doesn't contain any return statement or it only contains return statements without expression, the error messages are incorrect as the checker sees its return type as non-`never`. This commit takes into account that intersection types potentially reduces to `never` and improves error messages.
We have long speculated that intersections of object types with discriminant properties of disjoint types should be eqivalent to
never
(the empty type), since objects of such types are not possible to construct. This PR finally implements that feature.In addition to the intersection reduction implemented in #31838, an intersection
T1 & T2 & ... & Tn
is equivalent tonever
whenTx
types have properties with the same name, andnever
, andnever
.An example:
Previously,
AB
andBC
appeared to be object-like types withkind
properties of typenever
. Now, the types themselves arenever
because of the disjoint discriminant properties. This means that accessing properties on an empty intersection now produces errors, similarly to accessing properties on anever
value:Because empty intersection types are equivalent to
never
, they disappear from union types:Previously, an error was reported in the example because
x
was considered to have afoo
property of typestring | number
. With this PR there is no error because we treatB & C
asnever
, and thereforeA | (B & C)
is equivalent toA
.It is obviously uncommon to have type annotations that explicitly intersect disjoint types, as in the examples above. The root cause of empty intersections is typically instantiations of generic types that intersect type parameters.
Note that elimination of empty intersections causes an observable difference between
keyof (A & B)
andkeyof A | keyof B
, where previously the two were always equivalent. The former now producesstring | number | symbol
(equivalent tokeyof never
), whereas the latter produces'kind' | 'foo'
.This PR is technically a breaking change because code may exist that depends on empty intersections not being reduced away, even though this is incorrect from a typing perspective.
A note on the implementation of the feature:
In #31838 we reduce empty intersections to
never
immediately upon construction. However, in this PR we have to defer the determination because it requires us to resolve the types of properties in the constituent object types. Specifically, when two or more constituent object types have properties with the same name, we need to resolve the types of those properties in order to determine if they're disjoint discriminants, but doing so during intersection construction can easily cause circularities. So, instead of reducing intersections upon construction, we reduce them immediately before accessing members, relating them to other types, or converting them to their string representations in diagnostics and quick info. This is the purpose of thegetReducedType
function introduced by this PR.Fixes #36736.