[HN Gopher] PR that converts the TypeScript repo from namespaces...
       ___________________________________________________________________
        
       PR that converts the TypeScript repo from namespaces to modules
        
       Author : Kyza
       Score  : 189 points
       Date   : 2022-11-02 17:49 UTC (5 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | Kyza wrote:
       | > TL;DR: The TypeScript compiler is now implemented internally
       | with modules, not namespaces. The compiler is now 10-25% faster.
       | tsc is now 30% faster to start. Our npm package is now 43%
       | smaller. More improvements are in the works.
        
         | [deleted]
        
       | swsieber wrote:
       | > Finally, as a result of both of the previous performance
       | improvements (faster code and less of it), tsc.js is 30% faster
       | to start and typescript.js (our public API) is 10% faster to
       | import. As we improve performance and code size, these numbers
       | are likely to improve. We now include these metrics in our
       | benchmarks to track over time and in relevant PRs.
       | 
       | > [...]
       | 
       | > The TypeScript package now targets ES2018. Prior to 5.0, our
       | package targeted ES5 syntax and the ES2015 library, however,
       | esbuild has a hard minimum syntax target of ES2015 (aka ES6).
       | ES2018 was chosen as a balance between compatibility with older
       | environments and access to more modern syntax and library
       | features
       | 
       | I'd be curious as to what percentage of the improvement comes
       | from modules vs comes from a different target.
        
         | berkes wrote:
         | I'm curious about that too.
         | 
         | From my superficial knowledge of compilers, "modularization"
         | itself should not make code faster, if anything slower.
         | There'll always be some overhead of loading modules and
         | communicating between them, not?
         | 
         | I presume, from my own experience when building software (not
         | compilers), that modules allow for a much easier to reason
         | about, much better isolated (cohesion, loose coupling). And
         | therefore for much easier improvements inside the module. I
         | would presume that, here too, modules allowed them to improve
         | the inner workings much better, allowing for the performance
         | increase. Or am I completely misunderstanding this feature?
        
           | constexpr wrote:
           | There are two performance implications of "modularization":
           | initialization-time and run-time.
           | 
           | You are correct that initializing many modules is usually
           | slower than initializing one module [1]. However, bundling
           | puts all modules into one file, so this PR doesn't actually
           | change anything here. Both before and after this PR, the
           | TypeScript compiler will be published as a single file.
           | 
           | At run-time, switching to ES modules from another JavaScript
           | module system can be a significant performance improvement
           | because it removes the overhead of communicating between
           | them. Other module systems (e.g. TypeScript namespaces,
           | CommonJS modules) use dynamic property accesses to reference
           | identifiers in other modules while ES modules use static
           | binding to reference the identifiers in other modules
           | directly. Dynamic property access can be a big performance
           | penalty in a large code base. Here's an example of the
           | performance improvement that switching to ES modules alone
           | can bring:
           | https://github.com/microsoft/TypeScript/issues/39247.
           | 
           | [1] This is almost always true. A random exception to this is
           | that some buggy compilers have O(n^2) behavior with respect
           | to the number of certain kinds of symbols in a scope, so
           | having too many of those symbols in a single scope can get
           | really slow (and thus splitting your code into separate
           | modules may actually improve initialization time). This issue
           | is most severe in old versions of JavaScriptCore:
           | https://github.com/evanw/esbuild/issues/478. When bundling,
           | esbuild deliberately modifies the code to avoid the
           | JavaScript features that cause this behavior.
        
           | akiselev wrote:
           | For ES6 modules, the exports object is frozen (made read-
           | only) so the JIT can make some extra assumptions and
           | optimizations. With bundles, unless the bundler inserts
           | `Object.freeze` around `module.exports`, they have to be
           | treated as dynamic objects.
        
           | jakebailey wrote:
           | There are some key things here that maybe weren't clearly
           | stated in my writeup.
           | 
           | Firstly, the old codebase is TS namespaces, which compile
           | down to IIFEs that push properties onto objects. Each file
           | that declares that namespace is its own IIFE, and so every
           | access to other files incurs the overhead of a property
           | access.
           | 
           | With modules, tooling like esbuild, rollup, can now actually
           | see those dependencies (now they are standard ES module
           | imports) and optimize access to them. In this PR's case, the
           | main boost comes from scope hoisting.
           | 
           | For example, in one file, we may declare the helper
           | `isIdentifier`. In namespaces, we would write `isIdentifier`
           | in another file, but this would at emit time turn into
           | `ts.isIdentifier`, which is slower. Now, we import that
           | helper, and then esbuild (or rollup) can see that exact
           | symbol. All of the helpers get pulled to the top of the
           | output bundle, and calls to those helpers are direct.
           | 
           | That's why modules gives us a boost. There's also more
           | (modules means we can use tooling to tree shake the output,
           | and smaller bundles are faster to load), but the hoisting is
           | the big thing.
        
       | KingOfCoders wrote:
       | I don't care. I care when it's implemented in Rust. We've seen
       | reimplemtation of WebPack (in it's function as a transpiler) et
       | al. in something faster than Javascript. And I hope there is a
       | trend to decouple the language of the compiler from the language.
        
         | speedgoose wrote:
         | I think tooling of one programming language should be written
         | in the programming language. Otherwise the community will
         | hardly be involved.
         | 
         | All these rust tools may be slight faster, but typescript
         | developers will not learn rust to improve the typescript
         | compiler.
        
           | berkes wrote:
           | If you think of typescript as "tooling" that makes sense.
           | 
           | But if you think of it as compiler, or transpiler, not so
           | much. Python, Ruby etc "compilers" (runtimes, really) aren't
           | written in Python or Ruby. Or rather, there are alternatives
           | around, but they aren't the fastest nor the best. Such
           | "tools" are built in C. As are compilers for C++, Rust or
           | most languages really.
        
             | speedgoose wrote:
             | I understand your point. Compilers and interpreters are
             | traditionally written in C/C++, but we don't have to do the
             | same than before.
        
           | llanowarelves wrote:
           | What's the conversion rate on that though?
           | 
           | For smaller languages that are much less supported that makes
           | much more sense.
           | 
           | For bigger languages we treat it much more as a black box.
        
           | satvikpendem wrote:
           | > _but typescript developers will not learn rust to improve
           | the typescript compiler._
           | 
           | Why not? TS has much more in common with Rust than with JS,
           | in terms of typing. Compiler engineers are not that prevalent
           | in the community, but they are much more prevalent in the
           | systems engineering world which Rust is a part of, so I'd
           | assume it's actually _more_ beneficial to have a compiler in
           | Rust than in TS because it would mean more people interested
           | in contributing.
        
         | Kyza wrote:
         | I think a performance improvement in anything existing is
         | great. Especially for something as big as TSC. It has such a
         | large amount of usage that many people will appreciate. While
         | it would be great to have it reimplemented effectively in
         | something inherently faster, not improving what we have while
         | it's clearly still the best option wouldn't be helpful.
        
         | svnpenn wrote:
         | thats pretty harsh. I dont even like TypeScript/JavaScript, but
         | these are some pretty good numbers:
         | 
         | > The compiler is now _10-25% faster_. `tsc` is now _30%
         | faster_ to start. Our npm package is now _43% smaller_. More
         | improvements are in the works.
        
         | TAForObvReasons wrote:
         | In every single one of these cases, it begs the question
         | whether "JS" is the problem or "backwards compatibility". There
         | are a huge number of inefficiencies that can be fixed with a
         | full rewrite.
         | 
         | There was a recent conversation over ViteJS (a pure JS bundler)
         | vs rust-based tooling, and when you dig into the numbers the
         | real difference is SWC vs Babel. It raises the question whether
         | a new transpiler written in JS can be competitive with Rust,
         | but it's unclear if anyone tried.
        
           | RyanCavanaugh wrote:
           | Sucrase is written in JS and boasts the highest line
           | throughput of any competing transpiler
           | 
           | https://github.com/alangpierce/sucrase
           | Time            Speed
           | 
           | Sucrase 0.57 seconds 636975 lines per second
           | 
           | swc 1.19 seconds 304526 lines per second
           | 
           | esbuild 1.45 seconds 248692 lines per second
           | 
           | TypeScript 8.98 seconds 40240 lines per second
           | 
           | Babel 9.18 seconds 39366 lines per second
        
             | merb wrote:
             | but the benchmark is stupid: https://github.com/alangpierce
             | /sucrase/blob/main/benchmark/b...
             | 
             | > Like all JavaScript code run in V8, Sucrase runs more
             | slowly at first, then gets faster as the just-in-time
             | compiler applies more optimizations. From a rough
             | measurement, Sucrase is about 2x faster after running for 3
             | seconds than after running for 1 second. swc (written in
             | Rust) and esbuild (written in Go) don't have this effect
             | because they're pre-compiled, so comparing them with
             | Sucrase gets significantly different results depending on
             | how large of a codebase is being tested and whether each
             | compiler is allowed a "warm up" period before the benchmark
             | is run.
             | 
             | (worse it disables esbuild and swc's multi-threading... htt
             | ps://github.com/alangpierce/sucrase/blob/main/benchmark/b..
             | . https://github.com/alangpierce/sucrase/blob/main/benchmar
             | k/b...)
             | 
             | fake it till ya make it.
             | 
             | it's like saying "if I disable everything and wait for 5
             | minutes it's faster"
        
               | RyanCavanaugh wrote:
               | I don't see how this is a rebuttal to the claim. 636,975
               | is more than 2x 304,526, so assuming the quoted paragraph
               | is correct, sucrase is still the highest-throughput
               | transpiler even during its warm-up phase. Probably this
               | isn't true for the first 100 milliseconds of execution
               | during the very first warm-up stages, but if the
               | transpile phase is that short, it's basically irrelevant
               | anyway.
        
               | merb wrote:
               | the warm-up phase is the whole reason why esbuild and swc
               | exists btw. and also the sample is basically a small
               | hello world. any real project would do a little more and
               | the jit would not optimize as much.
               | 
               | also 2x 300k is not really the way how multi-
               | threading/concurrency/parallelism works... especially not
               | golang, which should not be run with GOMAXPROCS=1....
        
               | cxr wrote:
               | As far as I can follow your argument, it seems to be that
               | the native tools perform better on the small inputs (that
               | only ever take a second or three to complete), and that
               | the creators ("maintainers"?) of Sucrase have their thumb
               | on the scale or something, since they emphasize in their
               | results the very large inputs that will involve longer
               | running jobs where their tool has had a chance to warm
               | up. In other words, the tools you're defending only do
               | better when it doesn't really matter, and the tool you're
               | downplaying outperforms the competition on the jobs where
               | it actually does matter. If anything is backwards (or
               | "stupid", as you put it) then _that_ seems to be it.
               | 
               | Maybe I'm misunderstanding. In that case, please provide
               | a better benchmark.
        
           | ppseafield wrote:
           | SWC is written in rust, and Babel is written in javascript,
           | so you've proven the OP's point. Vite can be configured to
           | use SWC.
           | 
           | The recent conversation was about Vercel benchmarking a tuned
           | Turbopack+SWC vs. a default Vite+Babel, not really an apples
           | to apples comparison. When Vite is configured to use SWC as a
           | compiler, Vite's HMR gets faster; but it's not the default
           | for compatibility reasons.
        
             | longrod wrote:
             | Sucrase is faster or really close to SWC (see rhe
             | benchmarks https://github.com/alangpierce/sucrase).
             | Everyone still uses Babel because of the transforms.
             | 
             | And yes, Babel can also be made faster if enough effort is
             | dedicated into it. it's not an impossible feat.
        
               | ppseafield wrote:
               | For single core benchmarks only, correct?
        
       | tantalor wrote:
       | 500k lines changed, oof. Imagine the merge conflicts.
       | 
       | Could this not have been done incrementally?
        
         | jakebailey wrote:
         | This is as incremental as it really could be; the entire build
         | had to change, all of the code needed to be unindented one
         | level, etc.
         | 
         | I have tested the merge conflict problem, and thanks to the way
         | the PR is constructed (in steps), git actually does a good job
         | figuring things out.
        
       | darig wrote:
        
       | throwup wrote:
       | Does anyone have any insight about how to coordinate this kind of
       | change to a large project? This kind of thing touches literally
       | every file, so every branch will have merge conflicts. The best
       | idea I can think of is to announce the date ahead of time and
       | make every contributor rebase their branches on the day of the
       | merge. But there has to be a better way.
        
         | jakebailey wrote:
         | Surprisingly, at least for this PR, solving merge conflicts
         | turns out to not be too hard. By not squash merging it, we can
         | have a single commit that unindents the codebase all in one go
         | (and the commit is in the tree), which means that every line
         | has a clear path back to the current state of the main branch.
         | (And crucially, we can make git blame not point every line to
         | me...)
         | 
         | Potentially, an approach like this might be applicable to other
         | changes; I have a commit in my stack which moves the old build
         | system config to the new build system config's path (even
         | though it's wrong), as git does a much better job understanding
         | where the code is going if you help it.
        
       | longrod wrote:
       | Sucrase is proof that JS is not the problem when it comes to slow
       | performance. JS is not slow. NodeJS is not slow. It's the code
       | that is slow. All these people wanting to write it in Rust or Go
       | or XYZ programming language need to acknowledge this.
       | 
       | Yes, multithreading is awesome and really helpful but it's the
       | cherry on top, not the whole thing. If the same amount of effort
       | was put into optimizing the TSC codebase as it is being spent to
       | rewrite it in Rust, I have no doubt that it can become faster.
       | Perhaps it'll require some big changes but it won't create
       | compatibility concerns and it won't be a cat-and-mouse race
       | between the Rust version and the TS version.
       | 
       | I don't think "Write it in Rust" is always the solution to fast
       | programs. Rust itself can be pretty damn slow if you don't keep
       | performance in mind. That is why you have to optimize and profile
       | and optimize over and over again. Can't the same be done for TSC?
       | 
       | I think the biggest reason devs don't do this is because no one
       | likes profiling and optimizing since it is a slow and boring
       | task. Rewriting is so exciting! It's the thing you do when you
       | are tired of maintaining the old codebase. So just ditch it and
       | rewrite it in Rust.
       | 
       | I have nothing against Rust, mind you. I love what it has done
       | but I don't think rewriting everything is either feasible or even
       | the solution. And waiting for that to happen for every slow tool
       | out there is utter foolishness.
        
         | foobarian wrote:
         | How far can you get with JS/other interpreted things in e.g.
         | optimizing for cache access etc? Sounds like you're at the
         | mercy of the JIT compiler (which may go far, but still).
        
           | meheleventyone wrote:
           | With stuff like TypedArrays pretty far. Where JS has problems
           | is optimising in the face of the things you can do with the
           | language and the current difficulty in multithreaded
           | implementations.
        
           | TAForObvReasons wrote:
           | The interesting question to ask is whether these Rust
           | rewrites are really taking advantage of cache optimization or
           | if they are making simplifying assumptions that the canonical
           | implementation cannot. In the latter case, Rust isn't the
           | root of the performance difference and a JS rewrite can make
           | most of those simplifying assumptions
        
           | z3t4 wrote:
           | JavaScript does not have any input/output (IO/syscalls) all
           | those functions like reading a file, socket, etc needs to be
           | implemented in the runtime language, like the browser,
           | Node.JS, ASP, etc. So you are at the mercy of the runtime
           | executable. The JS JIT slows down startup time as the
           | JavaScript first have to be parsed and compiled before
           | running, but the runtime can then cache the compiled version
           | for faster startups. When JavaScript was new it was slow, for
           | example string concatenation was slow, but most JS engines
           | now implement string concatenation with a "rope" structure
           | making it very fast. v8 (Chrome) and Spidermonkey (Firefox)
           | have got a lot of optimizations over the years, so if you are
           | doing things like incrementing a number in a loop it will be
           | just as optimized as something written in a systems level
           | language.
        
             | CSSer wrote:
             | This can vary a ton as well. I was talking to a friend
             | yesterday who said he was pounding a native browser
             | interface with an iterator and experiencing slow
             | performance. He switched to buffering the entire thing into
             | memory first and experienced huge performance gains.
             | 
             | The aspect of the language you're using, if optimized, is
             | virtually always optimized for the most common use-case. If
             | your use-case isn't the most common use-case, you must
             | account for this.
        
         | [deleted]
        
         | notriddle wrote:
         | Yes, you technically can write high-perf JavaScript code...
         | 
         | https://github.com/alangpierce/sucrase/blob/153fa5bf7603b9a5...
         | 
         | But freaking _SIGH_ I don 't want to. I prefer coding in
         | environments that don't require unrolling loops by hand.
        
         | kasajian wrote:
         | When you write Chrome itself in JS, then you can talk to me
         | about performance.
        
           | eyelidlessness wrote:
           | AFAIK all of the major browsers (and other JS runtimes) have
           | implemented some performance-sensitive APIs in JS,
           | specifically because it performs better than crossing the
           | JS<->native boundary. Granted that's usually specifically
           | about JS API performance, but that's a lot of where
           | performance matters in a JS host environment.
        
           | cxr wrote:
           | Not sure if serious or not, but Firefox is a long-standing
           | example of this. It has always been a mixed C++/JS codebase.
           | (Since before it was even called Firefox, that is, though
           | nowadays, it's also Rust, too.) I routinely point this out in
           | response to complaints about the slowness attributed to e.g.
           | "Electron". JS programs were plenty fast enough even on sub-
           | GHz machines before JS was ever JITted. It's almost never the
           | case that a program having been written in JS is the problem;
           | it's the crummy code in that program. When people experience
           | Electron's slowness, what they're actually experiencing is
           | the generally low quality of the corpus that's available
           | through NPM.
           | 
           | Arguably, the real problem is that GCC et al are enablers for
           | poorly written programs, because no matter how mediocre a
           | program you compile with them, they tend to do a good job
           | making those programs feel like they're performance-tuned.
           | Today's trendier technology stacks don't let you get away
           | with the same thing nearly as much--squirting hundreds or
           | thousands of mediocre transitive dependencies (that are
           | probably simultaneously over- and under-engineered) through
           | V8 is something that works well only up to a point, and then
           | it eventually catches up with you.
           | 
           | Besides, there's no such thing as a fast or slow language,
           | only fast and slow language implementations.
        
         | merb wrote:
         | which proof? their faked benchmark?
        
         | Analemma_ wrote:
         | Sucrase consciously and deliberately breaks compatibility.
         | Which, to be clear, isn't necessarily a bad thing for some use
         | cases. But you can't really generalize from that to a tool like
         | tsc where this isn't an option. There might be a performance
         | ceiling here that can only be surpassed with a different
         | language.
        
           | swsieber wrote:
           | I suspect you have a point, given this line from the Sucrase
           | readme:
           | 
           | > Because of this smaller scope, Sucrase can get away with an
           | architecture that is much more performant but less extensible
           | and maintainable. Sucrase's parser is forked from Babel's
           | parser (so Sucrase is indebted to Babel and wouldn't be
           | possible without it) and trims it down to a focused subset of
           | what Babel solves. If it fits your use case, hopefully
           | Sucrase can speed up your development experience!
        
         | Chyzwar wrote:
         | Average node.js app is slow. It requires godlike
         | understanding/experience to make JS perform well. That why you
         | see people re-writing JS to rust and go and zig, for example
         | SWC, turbopack, esbuild and rome. For most use cases JS is
         | plenty fast but average go code will be faster and easier to
         | maintain.
         | 
         | As I am getting older, I do not want to spend my weekend
         | learning about new features in next.js v13[1]or rewriting tests
         | from enzyme to RTL[2]. I want to use programming language that
         | value its users time and focus on developer experience.
         | 
         | [1] https://www.youtube.com/watch?v=_w0Ikk4JY7U [2]
         | https://dev.to/wojtekmaj/enzyme-is-dead-now-what-ekl
        
         | __s wrote:
         | I rewrote a card game engine, openEtG, from JS to Rust. It was
         | a pretty 1:1 rewrite. 2x improvement even when I was using
         | HashMap everywhere. I've since entirely removed HashMap, which
         | has only further improved perf
         | 
         | As a bonus, the code is now statically typed
        
           | SquareWheel wrote:
           | I suppose it depends on your use case, but I don't really
           | consider 2x to be a significant difference. Between
           | programming languages we often speak in orders of magnitude.
           | 
           | If JS is only half the speed of a compiled language like
           | Rust, that shows remarkably optimized performance.
        
       | MitchellCash wrote:
       | > _a change in the indentation used in our bundle files (4 spaces
       | - > 2 spaces)_
       | 
       | I find it interesting that one of the reasons given for the
       | reduction in package size is due to such a simple indentation
       | change from 4 spaces to 2 spaces.
       | 
       | Not interesting that 2 bytes are less than 4 bytes, rather,
       | TypeScript is a large project and it would be interesting to know
       | how much size was saved from this one specific change? Seems like
       | a trivial change, so why not do it sooner? And assuming
       | readability isn't required in the bundle output why not bundle
       | with no indentation at all and put everything on a single line,
       | would this not be even smaller again?
        
         | IshKebab wrote:
         | Kind of funny because one of the benefits of tabs vs spaces
         | that people laugh off is that it saves space.
         | 
         | I think it's probably correct to laugh this off though. Why
         | would you care about the non-minified/gzipped size this much?
        
         | RyanCavanaugh wrote:
         | > Seems like a trivial change, so why not do it sooner?
         | 
         | Re: indentation: Literally, no one thought of it, as far as
         | anyone can tell. Linus's law appears to have its limits.
        
           | robertlagrant wrote:
           | Most minifiers already put things on one line, though.
        
             | jakebailey wrote:
             | TS has some unique restrictions due to downstream patching
             | of our package; my PR description briefly talks about this
             | as something we can try to improve in the future.
             | Minification absolutely would save a lot more size out of
             | our package, but I was not willing to change that in this
             | PR.
        
       | msoad wrote:
       | This opens up the door to going in there and replacing the slow
       | parts with Rust.
       | 
       | There is a lot of interest in making typescript fast but all of
       | them want to do a rewrite. Swapping the slow parts seems a lot
       | more viable
        
       | redox99 wrote:
       | I absolutely hate how with Typescript and ES Modules, if you have
       | a file
       | 
       | utils/foo.ts
       | 
       | you have to import it as
       | 
       | import Foo from "utils/foo.js"
       | 
       | Even though there is no .js file on disk, and you might be
       | running ts-node or whatever that doesn't build a .js file.
       | 
       | Importing a file that "doesn't exist" is so counterintuitive.
       | 
       | In addition all code breaks because you have to change all your
       | imports, and /index.ts or /index.js won't work either.
        
         | lewisl9029 wrote:
         | Agree completely. It also makes interop between Node and Deno
         | more painful. But there is hope on the horizon. :)
         | 
         | See https://github.com/microsoft/TypeScript/issues/37582 which
         | is referenced in the 4.9 Iteration Plan as "Support .ts as a
         | Module Specifier for Bundler/Loader Scenarios":
         | https://github.com/microsoft/TypeScript/issues/50457
        
           | cypress66 wrote:
           | But that doesn't seem like it would fix the typical flow,
           | there still would be no transpiling of imports. So yes you
           | could use .ts in ts-node, but you would have to use .js in
           | tsc. Which is pretty awful (you want your code to work with
           | both).
        
           | codefined wrote:
           | Actually looks to be tabled for TypeScript 5.0, release date
           | of 'March 14th' next year.
        
         | bigyikes wrote:
         | Every TypeScript project I have worked on either:
         | 
         | 1) enforces _no_ extension, e.g. "utils /foo", or
         | 
         | 2) allows TS extensions, e.g. "utils/foo.ts"
         | 
         | I have never imported a TS file using a JS extension. Maybe
         | your woes could be fixed with a configuration change?
        
           | Chyzwar wrote:
           | No, you were using non-standard ESM modules (compiled to
           | CommonJS defined by babel) Typescript recently added support
           | for ESM compatible with node.js see "module": "node16"[1][2]
           | 
           | The Whole ESM saga is clusterfuck, not much better than
           | python 2 -> 3 migration. Large node.js codebases have no
           | viable path to migrate, and most tools still cannot support
           | ESM properly[3]. Stuff is already breaking because prolific
           | library authors are switching to ESM.
           | 
           | As someone that maintain large part of TS/JS tooling in my
           | day job, I absolutely despise decisions made by node.js
           | module team. My side projects are now in Elixir and zig
           | because these communities care about DX.                 [1]
           | https://nodejs.org/api/esm.html#differences-between-es-
           | modules-and-commonjs       [2]
           | https://www.typescriptlang.org/docs/handbook/release-
           | notes/typescript-4-7.html       [3]
           | https://github.com/facebook/jest/issues/9430
        
             | redox99 wrote:
             | Yeah it's pretty ugly. This whole thing is a prime example
             | of those cases in which maintainers for mostly arbitrary
             | reasons decide on something and then absolutely ignore all
             | the massive negative feedback they get for this.
             | 
             | They'll cite some nebulous technical reasons of why it has
             | to be this way, but if you offer a PR that actually solves
             | the issue that the community complains about, they'll
             | reject it.
             | 
             | In this case they decided that tsc won't transpile imports.
             | They just did and it's "policy" and it can't be changed. It
             | doesn't matter if it is awful for compatibility, developer
             | experience, etc. It's just the policy. Issues will be
             | closed. And no, even an optional flag to transpile imports
             | is off the table, even if you write the PR for it.
             | 
             | There are many many issues opened related to this in
             | github, but to give an example
             | 
             | https://github.com/microsoft/TypeScript/issues/16577
        
               | Chyzwar wrote:
               | It is complicated but most user anger should be directed
               | to node.js module group[1]. TS is forced to follow
               | node.js standard.
               | 
               | [1] https://github.com/nodejs/modules/issues/323
        
           | cypress66 wrote:
           | And that's how it should work imo. But if you enable esm
           | (which you might need in the future because of packages being
           | esm only) you can't use those, only .js.
           | 
           | That's because typescript developers are dead set that they
           | don't want to transpile the imports, they just want to copy
           | paste them into the resulting file when running tsc.
        
             | conaclos wrote:
             | This could change with an ongoing work to allow ts
             | extension [1].
             | 
             | [1] https://github.com/microsoft/TypeScript/issues/37582
        
           | dickfickling wrote:
           | have you worked on Typescript projects using ES modules? What
           | you've described is the status quo for CommonJS modules, but
           | doesn't work when you switch to ESM (afaik, at least)
        
           | sebdufbeau wrote:
           | From my understanding, this is a fairly new predicament, for
           | projects that target ESM (type module in package.json)
           | instead of the default CJS
        
         | [deleted]
        
         | cush wrote:
         | Where are you seeing this? The PR that this thread is about
         | doesn't have this quirk. Maybe your setup has some issue...?
        
         | kuramitropolis wrote:
         | A thousand times this. It's not only the dumbest thing I've
         | seen a programming language do, it's also dumbest thing I've
         | seen in the JS ecosystem. Ended up having to implement an AST-
         | based post-processor to fix packages before publishing them.
        
       | zebracanevra wrote:
       | After this change, the TypeScript compiler will now be compiled
       | with esbuild. I feel like thats probably the best endorsement
       | esbuild could get, hah.
       | 
       | Surprising they call out the 2 space indent level that esbuild is
       | hardcoded[1] to use as a benefit. Why not save even more bytes
       | and re-format the output to single tab indentation? I wrote a
       | simple script to replace the indentation with tabs. 2 indent
       | size: 29.2MB, tabbed size: 27.3MB. 2MB more of indentation saved!
       | Not significant after compression, but parsing time over billions
       | of starts? Definitely worth it.
       | 
       | [1] https://github.com/evanw/esbuild/issues/1126
        
         | CodeWriter23 wrote:
         | > Why not save even more bytes and re-format the output to
         | single tab indentation?
         | 
         | For your answer search "programmers who use spaces make more
         | money"
        
           | throwup wrote:
           | I wish they had broken down that survey question further to
           | find out _how many_ spaces the highest paid developers use.
           | Then I could finally have a data-driven answer to put in my
           | prettier config!
        
             | tryfinally wrote:
             | Surely, on average, it's 3 spaces of indentation. Feels
             | great to finally be able to derive objective answers to
             | these ages-old conundrums!
        
           | jdrek1 wrote:
           | Correlation != causation
           | 
           | Spaces are simply inferior to tabs since the latter conveys
           | the meaning of "one level of indentation" while the former
           | does not. It's also better for accessibility and file size.
           | There is not one single logical reason to ever use spaces for
           | indentation, not one.
           | 
           | For some very fucking stupid historical reason someone in the
           | 80s made the idiotic decision of spaces being the default in
           | editors and people just went with it. The people earning more
           | are doing so because those are the seniors who have given up
           | on common sense and just go with the flow of the masses who
           | are unable to grasp "tabs for indentation, spaces for
           | alignment" yet insist on keeping alignment so the (terrible)
           | compromise is just using spaces. And I strongly question
           | whether "alignment" is worth anything, in almost all cases
           | it's just useless and in the rest you're drawing ASCII
           | diagrams in the comments which doesn't affect your code at
           | all.
           | 
           | Also see the top answer at https://www.reddit.com/r/programmi
           | ng/comments/8tyg4l/why_do_...
        
             | ddoolin wrote:
             | Tabs are denoted by arrows and I don't like being told what
             | to do! :)
        
             | lmohseni wrote:
             | Also for blind programmers, tabs are much nicer for a
             | screen reader.
        
             | jsyolo wrote:
             | What's the difference between indentation and alignment?
        
             | jcparkyn wrote:
             | > Tabs are simply inferior to spaces...
             | 
             | I think you wrote this the wrong way around?
        
               | jdrek1 wrote:
               | Ups, yes. I had it switched originally but then for some
               | reason switched it again. Apparently commenting late at
               | night is not a good idea.
        
             | CodeWriter23 wrote:
             | Testimonial: I experienced a significant increase in
             | earnings about 4 months after abandoning tabs for spaces.
             | Cause not known but that's what happened.
        
             | camjohnson26 wrote:
             | English is a bad convention too but we use it because
             | humans don't need the theoretically best systems to be
             | productive, they need something good enough. Spaces are
             | good enough, tabs are good enough, and anybody who gets
             | emotionally invested in one vs. the other is wasting time.
        
           | z3c0 wrote:
           | TLDR "Programmers who use spaces are more likely to respond
           | to StackOverflow surveys soliciting information about their
           | income."
        
         | robbick wrote:
         | I can see this is probably a calm point that will definitely
         | not escalate, programmers don't really care about tabs and
         | spaces that much, right???
        
           | bnt wrote:
           | Tabs
        
           | Accacin wrote:
           | Heh, I always wondered what the big deal was. I'll just use
           | whatever the company I'm working for uses and not even think
           | about it.
           | 
           | To be honest, that's why I love auto formatting cause I never
           | need to think about that stuff, I can just write code.
        
         | TOGoS wrote:
         | This was actually a significant issue in a large PHP codebase I
         | used to work on. Client hired a new guy who insisted that we
         | convert everything to spaces, and suddenly it took about twice
         | as long to check the thing out from Subversion.
        
           | ElijahLynn wrote:
           | That doesn't make sense that spaces vs tabs would result in a
           | 2x longer checkout. Something else is at play if that is the
           | case.
        
             | wombatpm wrote:
             | He did mention it was subversion
        
           | noduerme wrote:
           | Someone who comes onto a project and actually wants to charge
           | money to sit there and convert tabs to spaces or vice versa.
           | Incredible.
        
         | breck wrote:
         | Why a tab when 1 space will do?
        
           | marssaxman wrote:
           | Tab is ASCII 9 while space is 32. Tabs, having the lower
           | number, are therefore obviously cheaper.
        
         | Krizzu wrote:
         | Why not suggest this in the PR? Seems like it could be used in
         | pipeline to decrease size further down
        
       | siftrics wrote:
       | Jake Bailey was one of the best TAs I ever had in college. It's
       | great to see his name behind this.
        
         | jakebailey wrote:
         | I miss the Piazza days...
         | 
         | Thank you for the kind words!
        
       | iainmerrick wrote:
       | A little while ago I asked
       | (https://news.ycombinator.com/item?id=33051021):
       | 
       |  _I'm curious, how many people are using TSC only for type-
       | checking, and a different system (eg esbuild or ts-node) to
       | actually compile /bundle/execute their code?_
       | 
       | Looks like my suspicion was correct; not even tsc uses tsc!
        
       | simlevesque wrote:
       | The headline is pretty misleading. The TypeScript compiler isn't
       | implemented with modules. This is an open pull request which
       | would make it that way.
        
         | RyanCavanaugh wrote:
         | It's a PR that will be merged within the next week or so, and
         | has been scheduled in the TS roadmap for quite a while. It's
         | happening.
        
           | simlevesque wrote:
           | Hi Ryan, thanks for chiming in ! I just wanted to make it
           | clear that the current HEAD doesn't implement this but maybe
           | I'm just nitpicking.
        
         | Kyza wrote:
         | Oops, I didn't mean to mislead. I updated the title to be more
         | clear.
        
           | simlevesque wrote:
           | Thank you
        
       | breck wrote:
       | Bravo. This must have been painful. Super excited to use a faster
       | tsc. That will make a huge difference in our products. Thank you.
        
       ___________________________________________________________________
       (page generated 2022-11-02 23:00 UTC)