Repository navigation
Keep an own-line comment before a satisfies or as type on its own line - #19939
Conversation
`x satisfies\n// comment\nT` printed the comment on the `satisfies` line, which made it a trailing comment. The next format then moved it to the end of the statement, so the file took three passes to settle. The comment now keeps the line it was written on. Unions are left alone because they already break their members onto separate lines and would be indented twice.
commit: |
✅ Deploy Preview for prettier ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for prettier ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
All four done. Using
On the fixture: its case was Changelog trimmed. |
| node.typeAnnotation, | ||
| CommentCheckFlags.Leading | CommentCheckFlags.Line, | ||
| (comment) => hasNewline(options.originalText, locEnd(comment)), | ||
| ); |
There was a problem hiding this comment.
Is this the same as hasLeadingOwnLineComment?
Please answer directly under this comment.
There was a problem hiding this comment.
Almost, but not quite. The difference is CommentCheckFlags.Line.
hasLeadingOwnLineComment matches any leading comment whose end is followed by a newline, so it also catches a block comment that opens on the operator's line and closes on a later one. I tried swapping it in:
1 as /*
...
*/
Foo;
currently prints as 1 as /* with Foo; back at column 0, and with hasLeadingOwnLineComment it becomes
1 as
/*
...
*/
Foo;
which fails tests/format/typescript/as/comments. Inline block comments like 1 as /* c */ Foo are unaffected either way, since there is no newline after them.
So it is a behaviour change rather than a refactor. If you would rather multiline block comments broke that way too, I am happy to drop the flag and update those snapshots, it does simplify this to a single existing helper. I kept it narrow because the change was about line comments.
There was a problem hiding this comment.
The change to
1 as
/*
...
*/
Foo;
is expected. And I think it will fix the alignment issue cases that the comment is "indentable".
There was a problem hiding this comment.
Done, switched to hasLeadingOwnLineComment and updated the as/comments snapshot to the shape you quoted.
That drops the local hasComment call and the hasNewline and locEnd imports with it, so this file now uses the existing helper rather than its own variant.
Checked the four shapes are stable across two passes: the multiline block comment, a line comment on its own line, an inline 1 as /* c */ Foo, and a union with a comment. The inline one is untouched, since there is no newline after it. Rest of the suite is unchanged against this branch, same 17 pre-existing failures before and after.
The union check is still here rather than in shouldIndentUnionType, per the other thread.
There was a problem hiding this comment.
Add a test for "indentable" comment, can be a jsdoc.
There was a problem hiding this comment.
Please also add a changelog for it. We can add another changelog entry at changelog_unreleased/typescript/19939-2.md
| // then moves it to the end of the statement. A union already prints its members on | ||
| // their own lines, so it does not need the break and would be indented twice. | ||
| const keepTypeOnOwnLine = | ||
| !isUnionType(node.typeAnnotation) && |
There was a problem hiding this comment.
I think we should include union type here, but exclude in shouldIndentUnionType?
There was a problem hiding this comment.
I tried that and it regresses the long-line cases.
Adding (key === "typeAnnotation" && isBinaryCastExpression(parent)) to shouldIndentUnionType and dropping the union check here breaks as/break-after-keyword:
-const firstItem2 = ______________.items.find((item) => item.type === "item") as
- string | number;
+const firstItem2 = ______________.items.find(
+ (item) => item.type === "item",
+) as string | number;and worse on the one that already has a comment:
) as | a_union_will_break // comments
Three suites fail that way, as, as/break-after-keyword and flow/as-satisfies-expression. The indent after as is doing real work for line breaking, so removing it there is not free.
Unless you meant excluding it only when the type carries an own-line comment, which would keep the breaking behaviour and still move the knowledge into shouldIndentUnionType. I can try that shape if it is closer to what you had in mind.
Covers a block comment that opens on the operator's line and closes on a later one, which the line-comment-only check missed.
| // A comment written on its own line before the type has to stay there. Printing it | ||
| // after the operator makes it a trailing comment, and the next format then moves it | ||
| // to the end of the statement. A union already prints its members on their own | ||
| // lines, so it does not need the break and would be indented twice. |
There was a problem hiding this comment.
This comment is meaningless, let's dro.
There was a problem hiding this comment.
All three done.
Comment dropped. The jsdoc case is in as/comments, and it does show the alignment you predicted:
1 as
/**
* jsdoc
*/
Foo;
against stable, which leaves it hanging off the operator:
1 as /**
* jsdoc
*/
Foo;
Changelog added at changelog_unreleased/typescript/19939-2.md with that pair as the before and after.
There was a problem hiding this comment.
Stop saying "All three done.", just reply comments one by one. There is no context for "three".
There was a problem hiding this comment.
Understood, one reply per thread from here.
| @@ -0,0 +1,24 @@ | |||
| #### Keep a block comment before a `satisfies` or `as` type on its own line (#19939 by @Kjubikstronk) | |||
There was a problem hiding this comment.
Point out it's misaligned before in the title.
There was a problem hiding this comment.
Retitled to "Fix misaligned block comment before a satisfies or as type", so the heading says what was wrong rather than what it does now.
| const t1 = { | ||
| prop1: 1, | ||
| } satisfies | ||
| // Comment | ||
| Record<string, number>; |
There was a problem hiding this comment.
Use
const foo = {
bar: 1,
} as
// Comment
Record<string, number>;
There was a problem hiding this comment.
Swapped in, 9626796.
That shape shows the instability better than mine did. Stable prints } as // Comment on the first pass, then moves the comment to the end of the line on the second, so the changelog now has both stable outputs. I ran them rather than writing them out.
Description
typescript/satisfies-operators/comments-unstable.tsis listed infailed-format-tests.jsas unstable. This fixes it and removes the entry.The operator was followed by a hard
" ", so a comment written on its own line before the type was pulled up onto thesatisfiesline. That turns it into a trailing comment, and the next format moves it to the end of the statement, so the file needed three passes to settle.Keeping the comment on the line it was written on fixes the instability and leaves it where it was written, rather than at the end of the statement.
Unions are excluded: they already print their members on separate lines, so they do not need the break and would otherwise be indented twice.
typescript/union/consistent-with-flow/single-type.tsis unaffected by this change; it is unstable for a different reason (comments on union members) and stays in the list.Checklist
docs/directory).changelog_unreleased/*/XXXX.mdfile followingchangelog_unreleased/TEMPLATE.md.No new test is added because the fixture already exists; it was listed as unstable rather than passing, and that entry is now removed. Verified with the full
tests/format/js,typescript,jsxandflowsuites: the set of failing tests is identical tomainon my machine. I used AI assistance and reviewed everything before submitting.