-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
fix: Format Intersection same as Union #3988
Conversation
Share the same logic to format Interection and Union types in TypeScript and Flow. Closes #3986
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! LGTM, but I’d like to hear what other maintainers think about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a general rule, if there's complexity in prettier, it probably means that it's there for a reason and we didn't just do it for fun.
For more context, having |
be leading was already controversial, as the most common style from what I could tell was to make it trailing. We went through it because it made it line up nicely.
But for &, I've never actually seen people write it in a leading fashion. One of the big reason why is that you very infrequently have to chain them. & is there to build a bigger type, so you usually have one base type and one literal {}
.
Worse case is that you will have multiple variables that you chain with one literal. This one isn't super pretty right now but okay and not the common case.
I'm curious do you have a real example that motivated this? In the issue it's just made up code.
// The contents to write to stdin. | ||
stdin?: ?string, | ||
dontLogInNuclide?: ?boolean | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks worse to me
allowHalfOpen?: boolean, | ||
readableObjectMode?: boolean, | ||
writableObjectMode?: boolean | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only one that is arguable, but in my experience it's rare that you combine two variables with an object
I much prefer the current behavior |
@@ -321,13 +329,17 @@ type DataBase = { | |||
name: string | |||
}; | |||
|
|||
type UserData = DataBase & { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strongly prefer the inline version and agree with @vjeux's comments.
How about inlining (for both operators) an identifier/member expression at the beginning xor at the end? i.e. type foo = Foo & {
bar: Baz
}
type bar =
& Foo
& Bar
& {
baz: Quux
} |
A real-world example of when this formatting comes in handy, is when combining React HOC in a GraphQL-Apollo app, where I needed to construct a type combining many verbose types: // When creating an HOC
type Props = Subtract<InputProps, WithURLStateProps> &
RouteComponentProps<ProjectViewRouteParams>;
// A component that uses many HOC
type WithMergeIntentsMutationProps = WithAddIntentToClassifierProps &
MergeIntentsProps &
RouteComponentProps<ProjectViewRouteParams>; It might not be a common use case, but the formatting proposed in this PR makes this scenario much easier to read IMO. I like the solution proposed by @j-f1 |
Thanks for the concrete use case. This is the case where it's indeed debatable as to which is the best way. I've personally never seen anyone write those with a leading & in the past. It also feels confusing to me: if there's a space after Not sure how involved it would be to implement but adding a newline after // A component that uses many HOC
type WithMergeIntentsMutationProps =
WithAddIntentToClassifierProps &
MergeIntentsProps &
RouteComponentProps<ProjectViewRouteParams>; In any case, I'm reasonably happy with the current output and don't think that we should drastically change it. |
How do we feel about adding some heuristics to avoid breaking in some cases (for example, in |
@j-f1 we already shouldn’t break for type A = Foo & {
a: int
}; |
We do, however, break for multiple identifiers: Prettier 1.12.1 Input: type A = Foo & Bar & Baz & {
a: int
}; Output: type A = Foo &
Bar &
Baz & {
a: int
}; |
I'll close this as inconclusive |
Share the same logic to format Interection and Union types in TypeScript
and Flow.
Closes #3986