Skip to content

Improve formatting of TS casts with generics and unions#4219

Merged
suchipi merged 6 commits intoprettier:masterfrom
kpdonn:tsGenericAssertion
May 8, 2018
Merged

Improve formatting of TS casts with generics and unions#4219
suchipi merged 6 commits intoprettier:masterfrom
kpdonn:tsGenericAssertion

Conversation

@kpdonn
Copy link
Copy Markdown
Contributor

@kpdonn kpdonn commented Mar 28, 2018

fixes #4171
fixes #4168

Implemented by adding a soft break between the cast and the expression. Also includes wrapping parentheses for clarity as suggested in #4171.

Avoids changing behavior at all though if casting an array or object literal because those already have good behavior where the array or object literal breaks before the cast does so including them would just result in a pointless extra layer of parentheses that would add no clarity because the { } or [ ] wrapping the literal serves same purpose as the parentheses would.

never
>>(
someExistingConfigMap.mergeDeep(fallbackOptions)
);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about this formatting instead?

const stillTooLong = <
  Immutable.Map<
    string,
    boolean,
    number,
    object,
    null,
    undefined,
    any,
    void,
    never
  >
>(
  someExistingConfigMap.mergeDeep(fallbackOptions)
);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks better to me. It was a little more complicated to get working but I think I managed to do it.

Copy link
Copy Markdown
Member

@j-f1 j-f1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but I’d like to get some 👀 from other maintainers.

| never
>(
(<any>permissions)[receiverType]
);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it would be better not to break here after the cast. Have you tried splitting this in 2 groups?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not against the suggestion that it might be better not to break in this case but I'm not sure how to implement it.

The point of the PR is essentially to make the first choice for breaking lines with casts be between the cast and the expression being cast. The hope being better output in cases where both the cast and the expression then both fit on their own lines without further breaking like in:

  const breakAfterCast = <PermissionsChecker<any> | undefined>(
    (<any>permissions)[receiverType]
  );

The problem in the case you're talking about is that even after breaking the cast and the expression onto their own lines, the cast still doesn't fit onto a single line and has to break more.

So what I can't figure out is a way to tell it "try to break on the outer group first, but if that doesn't make the subgroups fit onto their own line then undo the outer break and just break the subgroups."

Any thoughts?

@kpdonn
Copy link
Copy Markdown
Contributor Author

kpdonn commented Mar 29, 2018

@duailibe Figured out a way to have it work the way you suggested by using conditionalGroups.

@ethanresnick
Copy link
Copy Markdown

@kpdonn Thank you for this! The output looks way better.

In general, I'd still like to see prettier be more willing to break an assignment after the = sign in those cases when the putting the RHS on its own line would save it from wrapping (or, perhaps more generally, when starting the RHS on its own line would make the whole assignment statement take fewer lines than not breaking there). I think programmers go through that kind of formatting process all the time, and it usually makes the results just that last bit nicer. I don't know very much about prettier's internals/primitives, though, so idk how easy that is. It's also probably a separate PR regardless, though I'd be curious to hear peoples' thoughts on this idea.

In the meantime, thanks again!

Comment thread src/language-js/printer-estree.js Outdated
typeAnnotationGroup,
">",
ifBreak("("),
indent(concat([softline, path.call(print, "expression")])),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could just wrap this in a group. The thing here is, when the typeAnnotationGroup breaks, it will also break the parent group, which will then make the behavior you are seeing.

But if you wrap this part here in a group, the fact that the parent is "broken" won't affect a child. It will try to print in a single line before breaking.

I'll try my suggestion in a bit and report back :-)

@lipis
Copy link
Copy Markdown
Member

lipis commented May 6, 2018

This have been recently talked in the Twitterverse :) What's the latest..?

kpdonn added 6 commits May 7, 2018 22:00
By adding a soft break between the cast and the expression. Also
includes wrapping parentheses for clarity as suggested in prettier#4171.

Avoids changing behavior at all though if casting an array or object
literal because those already have good behavior where the array or
object literal breaks before the cast does so including them would just
result in a pointless extra layer of parentheses that would add no
clarity.
Specifically it will break after the cast if that makes the cast itself
fit on a single line. If the cast itself won't fit on a single line then
the expression being cast will be placed directly after the `>` at the
end of the cast.
@suchipi suchipi force-pushed the tsGenericAssertion branch from c5741fd to cbd1229 Compare May 8, 2018 04:02
@suchipi
Copy link
Copy Markdown
Member

suchipi commented May 8, 2018

Rebased on master; I'll merge this once CI finishes. Thank you for the fix @kpdonn!

@suchipi
Copy link
Copy Markdown
Member

suchipi commented May 8, 2018

Failure is unrelated

@suchipi suchipi merged commit c6e7c19 into prettier:master May 8, 2018
@lipis lipis added this to the 1.13 milestone May 9, 2018
@lock lock Bot added the locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting. label Jan 18, 2019
@lock lock Bot locked as resolved and limited conversation to collaborators Jan 18, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ugly formatting for Typescript generic type type assertion Very ugly formatting for Typescript union type type assertion

6 participants