-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Erroneous compiler error when using generic intersection type as generic class parameter #14022
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
Comments
Broken by #12643. The break may have been intentional; I need to re-read the change. |
After looking at #12643, I'm not yet sure whether the example should be legal or not, but I do know that it worked by mistake previous to the change. Before #12643, The breaking change happens in I'm not sure whether |
Appreciate your looking into this! I am using this structure to create abstract, reusable React components with TypesScript. A simplified example might be something like the following: abstract class Dialog<P, S> extends React.Component<P, S & { submitButtonText: string }> {
f() {
this.setState({ submitButtonText: '' });
}
}
class SignUpDialog extends Dialog<{}, { userName: string }> {
g() {
this.setState({ userName: '' });
}
h() {
this.setState({ submitButtonText: '' });
}
} This way the abstract components can still manage the state that they are aware of. The compiler logic is a bit over my head, but in the above example the error is only thrown on the statement in |
Hm. @ahejlsberg, can you take a look? It looks like |
I think the current behaviour is correct but unexpected. The explanation is given here. I guess using spread types instead of intersections would yield the expected result. |
In this case we do know some properties of |
|
This might be a bit off track, but I'm surprised the result of conflicting properties on an intersection type, where any one conflicted property is a primitive, is an intersection of those properties (how can a |
@gcnew Oh, I see now. You are right, it is surprising but unfortunately correct that @jacamera The usual case for intersections is either no overlap or agreement in types. Intersecting conflicting types is just a fallback that is correct once in a while, and unusable the rest of the time. |
Understood. Thanks again for your time. To anyone else who finds this, the dialog example from above can be rewritten in the following way to avoid any compiler errors. The only downside I see is that all the properties of the abstract component's state type have to be optional so the compiler can't enforce the required properties in the initial state assignment. interface DialogState { submitButtonText: string }
abstract class Dialog<P, S extends Partial<DialogState>> extends React.Component<P, S> {
f() {
this.setState({ submitButtonText: '' });
}
}
class SignUpDialog extends Dialog<{}, Partial<DialogState> & { userName: string }> {
g() {
this.setState({ userName: '' });
}
h() {
this.setState({ submitButtonText: '' });
}
} |
TypeScript Version: 2.1.6 and 2.2.0-dev.20170212
Code
Expected behavior:
Code compiles without error. Worked fine with 2.2.0-dev.20161204 and broke on 2.2.0-dev.20161205.
Actual behavior:
The following error is generated:
The text was updated successfully, but these errors were encountered: