prettier: Typescript/Flow: Inconsistent union and intersection type multiline formatting
Prettier 1.10.2 Playground link
--parser typescript
Input:
type IntesectionType = VeryLongTypeA & VeryLongTypeB & VeryLongTypeC & VeryLongTypeD & VeryLongTypeE
type UnionType = VeryLongTypeA | VeryLongTypeB | VeryLongTypeC | VeryLongTypeD | VeryLongTypeE
Output:
type IntesectionType = VeryLongTypeA &
VeryLongTypeB &
VeryLongTypeC &
VeryLongTypeD &
VeryLongTypeE;
type UnionType =
| VeryLongTypeA
| VeryLongTypeB
| VeryLongTypeC
| VeryLongTypeD
| VeryLongTypeE;
Expected behavior:
type IntesectionType =
& VeryLongTypeA
& VeryLongTypeB
& VeryLongTypeC
& VeryLongTypeD
& VeryLongTypeE;
type UnionType =
| VeryLongTypeA
| VeryLongTypeB
| VeryLongTypeC
| VeryLongTypeD
| VeryLongTypeE;
I think the Interections type should use the same format as the one used for the Union type.
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 38
- Comments: 17 (6 by maintainers)
The proposed behavior is growing on me. I see the argument about
but that could also be special cased.
What I wrote:
What came out:
đ
Also I just noticed that with
--parser flow
the output is much betterThis is still a problem, IMO. E.g. the following code constructs a type, which includes properties from type
A
except those present inBar
or given object type (effectively{ ...A, ...Bar, ...{ baz: string } }
):The intersection expression has three members:
Pick<...>
,{ ... }
andBar
, and I expect to see each one on a separate line (if the whole expression doesnât fit print width):But Prettier wraps it in pretty unreadable and non-sematic manner:
FYI: Prettier wraps non-type expressions in desired manner:
becomes
Also, I agree with @albertorestifo that formatting with leading
&
is preferable, but it isnât critical.It would be nice to special-case it for
|
, too.Just set up prettier in a large-scale project, and this was definitely a bizarre issue to run into. I would love to see this revisited. The inconsistency between intersection and union has definitely been a hit in readability for our team. Also, my biggest frustration with it is we have a number of intersections that we regularly add to, and not being able to just copy the last item down and edit it is pretty annoying
Also, as mentioned above, the primary case that seems to be used to justify the inconsistency (shown below) seems easy enough to special case, and probably should be special-cased for both intersections and unions. It certainly doesnât feel like there is enough benefit to warrant the inconsistency, and it seems to be less readable in almost anything besides the below use case
https://github.com/prettier/prettier/issues/3986#issuecomment-369059369
I canât help but think that it would be a lot simpler maintenance-wise to just treat intersections the same as unions.
Currently intersections have their own unique logic so canât easily be standardised to format the same as binary expressions - theyâre going to need their own, custom logic in order to look good - which will increase the maintenance burden over time as more edge cases are found (and introduced by new syntax). Example of bad formatting just for intersections: https://github.com/prettier/prettier/issues/14726, #14773.
If we instead formatted multiline intersections the same as unions - with a leading
&
and each member on its own line - then there would no longer be any additional branches to maintain.I wonder if itâs time to revisit this change with the looming v3 major release? A major release would be the perfect time to make this sort of change.
As an aside - itâs worth noting that this sort of thing doesnât impact flow that much now-a-days because the vast, vast majority of flow object types are merged via spreads
{...T, ...U}
and intersecting them often leads to weird behaviour in the type system. This is in contrast to TS where there is no spread syntax so the only options for merging object types is by intersecting them or by using interfaceextends
.Hi everyone,
I donât really understand why https://github.com/prettier/prettier/pull/3988 has not been accepted, and what is intentional by having the current formatting behavior. When you start having complexe type (with options, inferences, etc) the current formatting prevent the developer to quickly understand your code and eventually end by being unmaintainable.
The arguments put forwards are:
For the 1st one, lot of people would like but canât as we mostly use prettier for our syntax formatting, and whoâs doesnât use tools for formatting are probably not a good example to follow đ
For the 2nd one, it is the same issue with the pipe
|
operator. BTW we use this operators for intersection and union because they behave as it would on binary numbers. If there was a XOR (^) operator for typescript types it would work (for object/record it would means âunion + removing same keysâ).So, can we debates on this and close this issue ?
Thanks
@tommarien we can fix it without milestone 3
i didnât realize the original issue was for typescript. but i guess itâs still relevant for flow as well đ
Seems pretty straight forward to fix. Iâll try to make a PR during the weekend