Hacker News new | ask | show | jobs
by pauliusj 1674 days ago
My only wish is that the compile times were faster. I know typically people will say there's incremental compilation, but I think this problem leaks into many other places. Like vscode suggestions, go to definition, custom build scripts for which you may need to process types etc. I recently had to use eclipse for some java work and it seemed lightning fast in comparison. This is my only (pretty big) complaint about TypeScript, otherwise it's a very useful tool
3 comments

If you separate compilation from type checking, the compilation stage is instant. If it’s not, spend the hour or so to understand how to rework your tooling so that it’s working properly. It’ll pay off by the end of the same day.
I have to admit i’m baffled by this suggestion. I get that compilation and type checking offer different value propositions, but i’ve now walked into a couple of projects that were happily compiling their typescript with babble only to realize once compiling with tsc that there were rampant type errors.

I find this idea of throwing away safety for compilation speed to be a non-option.

It’s a perfectly fine option because it’s happening at developer time when you don’t care if it’s wrong. You’re IDE is likely providing typing insights anyway so waiting for the totality of the compilation to see the result of reloading your app isn’t necessary. It’s like using a potentially wrong cache that’s alerts your after the fact that the answer was invalid. Rather than waiting, you proceed to examine the results and likely refine your work before the relatively slow type checker validates the universe.

Now if you end up pushing code that hasn’t been type checked then that’s a different story. Might as well run “git yolo” if you’re not going to run type checks, linting or any other sanity tests before indicating you’re own personal sign off of a commit.

This just seems like a really long turn around time for type errors. This pushes global type checking into the space of unit testing in terms of time cost. I'd personally much rather have tsc take a second or two and give me the full picture than just hide my eyes until I run unit tests.
Could you elaborate?

Shouldn't the type checks happen while you write the code?

vscode + typescript seems to only surface errors in the current file. If a change breaks something in another file it isn't apparent (in my experience at least). I added tsc to a pre-commit hook to catch these issues.
Interesting.

I had the impression it would also include imported files.

Thanks! :)

Your CICD should validate types and lint and fifty other things. The developer when running a local compile does not need to but should before pushing.
Think about the various tools we have available to us in concentric rings, each with an increasingly longer period.

In the inner most ring, the most readily available, happening almost instantly, we have tools like syntax checking, maybe even LSP calls, linting. Time since writing the code is on the order of ms to a second.

In the outermost ring, the least available we have CICD, these checks happen rarely, often on a push to a central server. Time since writing the code is on the order of 10s of minutes to potentially hours.

I have a really hard time believing that folks are getting so little value out of types, have so few project wide issues, or are so willing to rewrite portions of their work to push type checks into the outer ring of CICD.

That's not what's happening. They're not pushing type checking to the outer ring. They are pushing cli driven gold standard type checking to an intermediate ring and worst case the outer ring. Their IDE can do 95+% of the type checking anyway and only when it fails do they need to escalate. However that escalation is rare and does not need to be done every single time they wish to compile something for local testing.
Decoupling build and typecheck is definitely a good first step, but poor typecheck performance is still going to eventually become a bottleneck in CI as project sizes increase.

At Brex we were running up against typecheck times of over 15 minutes at one point before we were forced to address it since it was frequently creeping onto the critical path. We ended up hacking together some CI scripts to share the incremental typecheck cache between builds, which made most checks reasonably fast again (usually well under a minute, averaging 10~ seconds), but there are still frequent large spikes (of 5-15 minutes) in typecheck times on tiny, seemingly innocent changesets (with few dependent files as far as we could tell) that can still really take a toll on productivity.

I believe the recommended solution to scale typecheck performance is to break down your app using interdependent project references that serve as atomic units that only get rechecked if they change, but I'm personally not a fan of this approach because most frontend projects don't really derive any intrinsic benefit from this style of organization (as they function perfectly fine as monoliths, and any added indirection only adds unnecessary friction), and project references themselves have a bunch of caveats and introduce a ton more tooling complexity: https://www.typescriptlang.org/docs/handbook/project-referen...

I wish instead of having to break down our apps into project references manually to reap the performance benefits, TypeScript could just treat each file as a "project" onto itself and give us those performance benefits automatically and by default. In the ideal world I should be able to just run `tsc --noEmit` with the list of files changed from git, and have typescript do the minimum possible amount of work to check all the potential files affected by the changed input files by walking up their dependency graphs, without having to structure my project in a certain way.

Is what you’re asking for possible?

JavaScript can walk both directions on a dependency graph. You can import two things and inject the first dependency into the second.

So, unless you want to “structure your project a certain way,” you’re out of luck. If you ARE willing to conform to those patterns then you can get incremental builds.

As it happens, you can get something similar within a file by declaring a type interface, telling the compiler “you don’t need to walk the interior of this function because look see here’s the signature,” but you lose the power and dynamism of implicit types / complex generics by doing this.

I could be wrong about this; it’s been a minute since ts was my daily driver.

It's late here, looks like I did a few wording mistakes. The actual compilation (turning ts/tsx into js) is very fast and not a problem at all, what I meant is the typechecking
Interesting, I'm generally quite sensitive to small delays when typing/seeing autocomplete, but this hasn't been much of an issue for me, even in VSCode. But maybe that's because I only enable extensions on a per-workspace basis.

Regarding build times, have you tried using esbuild (https://esbuild.github.io)? It's ridiculously fast.

vitejs uses it in their dev mode (https://vitejs.dev) if you wanna give it a shot without spending too much time fiddling with configuration.

The creator of SWC [0] is working on a faster compiler alternative in Rust, so there is still hope for a faster compilation speed in the future

[0] https://github.com/swc-project/swc

SWC doesn't do type checking, which means 99% of the work is just stripped type annotations. That's why it's fast.
It will, which is what the grandparent is talking about. https://github.com/swc-project/swc/issues/571
Ah very neat. Didn't know about that! Though I would be very surprised and impressed if that effort actually succeeds.