TypeScript: Emit does not preserve empty lines
Hi,
TS Version: 1.1
Given
function foo() {
var x = 10;
var y = 11;
}
We used to get
function foo() {
var x = 10;
var y = 11;
}
In the new compiler the line break is missing
function foo() {
var x = 10;
var y = 11;
}
(Both compilers removed the first empty line, but the new compiler has gone a step further.)
This can affect the experience when debugging JavaScript in the browser.
About this issue
- Original URL
- State: closed
- Created 10 years ago
- Reactions: 79
- Comments: 45 (9 by maintainers)
Commits related to this issue
- Do not include js files in TS compilation problem: in compilation tsc removes blank lines from the file this causes problem in debugging and mapping with IDEs https://github.com/microsoft/TypeScript... — committed to lpranam/online by lpranam 3 years ago
- Do not include js files in TS compilation problem: in compilation tsc removes blank lines from the file this causes problem in debugging and mapping with IDEs https://github.com/microsoft/TypeScript... — committed to CollaboraOnline/online by lpranam 3 years ago
The crowd wants
preserveWhitespace: true/false@ORESoftware ++This shouldn’t be that hard, shouldn’t there just be an option in tsconfig.json
preserveWhitespace: true/false?
I would also like this for a similar reason as @timjmartel - when developers see the emitted JS looks nice they are less resistant to adopt. Preserving (at least vertical) whitespace makes the code look less like it was generated by a machine and more like idomatic JS code written by a human.
If our team ever decided to abandon TS and instead continue with the transpiled JS it would be much easier to adopt the emitted JS sources if they had human-friendly whitespace.
Reason this is important is that TypeScript is supposed to “degrade gracefully” to JS. Right now it can’t preserve new lines making the JS a bit dense to read, especially if you write TypeScript, but you are supposed to deliver JS to some place else.
I don’t think using esformatter solves the whole problem. Sure, it can automatically insert blank lines around functions etc. But for me, blank lines within functions are even more crucial. We use blank lines like paragraphs in prose: to group individual thoughts.
Those blank lines within functions help to communicate the structure of the function. Without them, I find that readability suffers.
As an engineering director exploring moving our javascript development community to typescript the new line capability would really help. One of the primary appeal of typescript was maintaining the readability and structure of the code created in typescript generatedJavascript.
Great to see comments are kept in the recent update and addition of the “–removeComments" command line directive.
I would also like to see this implemented, with a few specific reasons in mind:
This PR, discussed in the 3.9 release notes, show code actions preserving newlines; why can’t the emitted code do something similar?
I was part way into trying to fix this in the compiler itself when my teammate @emadum reminded me that tsc can preserve comments. Here’s a little gulp pipeline that seems to do a fairly decent job of preserving newlines:
I think a more clever comment would prevent some false positives, but it seems to work well for us today. I’ve only tested this on a relatively small file, but the performance overhead there was minimal.
hth
Adding some background info… The reason the new compiler removes all blank lines is that this is the only thing we can do consistently. Blank line preservation is always going to be a hit or miss thing when it comes to constructs that are subject to rewriting, e.g. class and module declarations. We face exactly the same issues with comment preservation. So, while I’m sympathetic to resolving this, it’s not an easy thing to do.
@NoelAbrahams I’m curious what issues you see when debugging?
I just realized. One good reason to not keep whitespace is that it will really help prevent you from accidentally editing the .js instead of the .ts. I guess one thing to do would be to write out the .js files as readonly/execute only. So maybe this is a non-issue.
That being said, I don’t think tsc writes out .js files as readonly/execute only, is there a way to configure tsc to do this?
I’m changing this to Won’t Fix. Reasons:
@ahejlsberg @NoelAbrahams There is one issue that exists with debugging in the browser that is slightly related to this conversation. When using setter/getter chains (like with jquery) or chaining promises, the new line feeds are lost during translation. That being said, it is a huge pain point when working with Arrow functions.
As an example:
Becomes:
Using Chrome and sourceMaps, the breakpoints are still skipped.
http://www.typescriptlang.org/Playground#src=(<any> x).a(‘%23test’) .b(‘test’) .c(() %3D> ‘foo’)%0A%09.d(()%20%3D%3E%20’bar’)%0A%09.e(()%20%3D%3E%205)%0A%09.f(()%20%3D%3E%206)%3B
I also run into this issue. I came up with a workaround by creating a diff patch and revert whitespace changes in the patch. jsdiff allows you to create a structured patch object and manipulate it as you wish.
With this workaround, you can preserve all the line breaks from the original file.
+1
preserveWhitespace: true/falseTemporary hack
Use esformatter to add linebreaks.
With the following configuration file:
It depends on your exact needs. There are several suggestions in this issue and a list of other transpilers is as follows. Note that this list hasn’t been sanitized for the specific requirement:
Are there any updates for almost 10 years? I would like to be able to configure preserving new lines
@mbroadst
I ended up using your idea as a base, and eventually expanded upon it until it became an npm module: https://www.npmjs.com/package/gulp-preserve-typescript-whitespace
I credited your post in the Readme, hopefully you don’t mind 😃