HN user

jakebailey

118 karma

[ my public key: https://keybase.io/jakebailey; my proof: https://keybase.io/jakebailey/sigs/CF2PFxpUflWXTNBGfraOsTOTbcP2iI8duvVRGmBoPNg ]

Posts0
Comments20
View on HN
No posts found.
TypeScript 7 14 days ago

Hoping to start getting Wasm builds out soon; it's a little unclear what people want when they say "Wasm", because it could mean

- LSP monaco - the API in the browser - the CLI in Wasm for platforms we couldn't build

which muddies the water a bit, but I'm sure we can get it working

The automatic generation was mainly a step to help with manual porting, since it requires so much vetting and updating for differences in data layout; effectively all of the checker code Anders ported himself!

This is specifically about the performance of the TypeScript toolchain (compiler, editor experience); the runtime code generated is the same. TypeScript is just JS with types.

Until trademark laws come into play, and you find yourself obligated by law to give up your domain username to a big corporation.

This wouldn't be a big deal in practice (besides losing the domain). Domain usernames are just the combo of you telling Bluesky "I intend to use this domain name" and then you placing a TXT record on the domain to prove you own it. If you want to change domains (or, are forced to), you just give them the new domain name and you set another TXT record (just like if you had set up a domain name as a username for the first time). The underlying DID is still yours.

One of my major gripes with the JS/TS ecosystem is that "explanations" are sorely lacking. See https://www.typescriptlang.org/tsconfig for the relevant documentation for tsconfig files. Tutorials are on the page, how-to guides abound on the wider internet (like the OP), and the linked TSConfig Reference and JSON Schema (used in code completion in IDEs) are together absolutely massive.

But an explanation is missing! There is no official documentation about how different options interact to say: as I'm walking a file tree as the Typescript compiler, this is how I will interpret a certain file I encounter, what will be outputted, and how that will be interpreted by bundlers and browsers, especially in an ESM world.

Perhaps you missed it, but Andrew (from the TS team) recently finished a massive overhaul of our module docs: https://www.typescriptlang.org/docs/handbook/modules/introdu...

The "theory" page describes TypeScript's perspective on modules. The "reference" page documents things from the "as I'm walking a file tree" perspective (among many other details). The "guides" page also provides recommendations for certain kinds of projects.

TypeScript 5.0 3 years ago

Ah, sorry; I brainfarted and missed the ".ts" part. I was thinking of the ".js" extensions, which are required in newer resolution modes (but are supported in older ones, and therefore using the strictest mode produces the most compatible code).

TypeScript 5.0 3 years ago

Sure, we don't bump according to semver, but it's hard to say that 5.0 _isn't_ a major release given how we used it as a way to get a bunch of breaking changes and cleanups in. It's a very opportune time as people will be forced to manually upgrade and acknowledge that something is changing.

It's not perfectly cut and dry, but mostly. We still need to emit d.ts files for our public API, and the only thing that can do that is tsc, which will type check.

But I tried my best to make the build have fast paths to minimize the development loop as much as possible.

No formatter would support having code indented like that at the top level for no reason, so that's not an option. Though, I have been looking into getting us to use a formatter, period (right now we don't).

I didn't consider doing it step by step, no, but I'm not sure how I would really achieve that effectively. The reality is that the bulk of PRs are submitted by the team, and it's straightforward to get everyone to get their code in before this change, pause merges, rebase, and then continue as normal. I'd rather go for the "rip the band-aid off" method.

I think it's the case that modules are the future; but the main focus of this change was not actually performance at all. We've been wanting to be able to dogfood the modules experience (used by most TS devs) for a long time. The fact that it turns out to be so much faster is a really great side effect.

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.

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.

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.

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.