Working on TypeScript at Microsoft. I appear when someone says “module resolution” three times in the dark. He/him

Marin, CA
Let’s look at each piece of this to go over what it does, why it is (or more often *isn’t*) needed, and why I can tell this package.json is misconfigured just from this small snippet. 🧵
It is *crazy* how ALL of this is needed to just publish a package in today's JS ecosystem...
25
141
1,235
550,490
Want a view of what the TypeScript compiler sees in your project? ⏱ tsc --extendedDiagnostics How long stuff took and how big/complex it is. 📜 tsc --listFiles List of every file included in the compilation. 🧠 tsc --explainFiles List of every file and *why* it’s included.
3
81
447
Since February, I’ve been spending part of my time rewriting TypeScript’s modules documentation, replacing years-outdated content and adding some that’s never been written down. There’s always more to write, but I’m publishing it officially today. 1/5 typescriptlang.org/docs/hand…
8
58
421
85,063
One small quality of life improvement for frontend devs in TypeScript 4.3: you can now jump into imported files TypeScript doesn’t understand, like CSS.

ALT Command clicking the module specifier on `import "./index.css"` opens the CSS file in VS Code.

5
44
319
Of the TypeScript features I’ve worked on, this may be the one I’m personally most excited to use: better support for `require` in auto-imports for plain JS.
8
34
179
New things: I’m joining the #TypeScript team starting next week! Incredibly excited and grateful for the opportunity to work full-time on a product I love and use daily. So much to learn! 😍
5
5
158
What if TypeScript libraries published just .ts sources to npm instead of .js and .d.ts files? This might already be tempting for Bun-only libraries, but how will that impact users? This is easy to answer by experimenting on existing libraries that ship .js, .d.ts, *and* .ts. 🧵
What if Node supported TypeScript?
11
19
178
101,075
Holy smokes, @Netlify’s onboarding experience for an existing @gatsbyjs site is *incredible.* I... think I just migrated my blog in like... 5 minutes (plus waiting for DNS propagation)? 🤯👏🏼
5
4
149
📢 Feedback wanted! TypeScript 4.4’s auto-imports will show you the proper import specifier, respecting path mappings and node_modules, instead of the direct path to the exporting file. You can try it out now with VS Code Insiders and TS nightly. marketplace.visualstudio.com…
5
16
159
This is now shipped in TypeScript 4.3 beta and VS Code Insiders! Help me out by giving it a try and reporting any issues you find on GitHub 😄
Folks are going to love this (hopefully 4.3) TypeScript import change from @atcb github.com/microsoft/TypeScr…
7
24
134
Hey @github you probably know this by now, but it seems like ⌘-enter is now closing issues instead of just posting comments, and chaos is reigning supreme
4
4
125
There seems to be a common misconception that this will work. TypeScript will not read JS files inside node_modules by default. Writing JSDoc is great, but you still need to generate declaration files before shipping to npm.
If you write a library in .ts files, when you publish at a minimum you’ll have 2 files for every source file: a .js file with your implementation and a .d.ts file with all your declarations. If you publish source maps (sourceMaps: true) you will also have a .js.map file. If you publish source maps for your declaration files (declarationMap: true) you will also have a .d.ts.map file. So, 4 files in the output bundle for every 1 .ts file. Contrast that with using JSDoc in a .js file and checkJs: true. All the benefits of TypeScript, and no proliferation of files when you publish.
4
13
98
61,378
When #Xamarin joined Microsoft, I knew there would be some changes, but I wasn’t expecting this:
2
76
89
If you’re writing TS code and running the output in Node—no bundler, esbuild-kit/tsx—and you don’t have "module": "nodenext", "moduleResolution": "nodenext" things are going to be very broken for you. Node will fight you every step of the way and TS won’t help. Let TS help.
3
4
86
41,109
7. I’m on vacation and can’t believe I just got baited into thinking about modules for this long, but at work, I’m writing TS-centric docs for all this stuff, and I also have a WIP tool for validating packages to catch the TS-specific problems I addressed: arethetypeswrong.github.io
2
5
82
10,361
Almost everyone: [incredulous angry noises involving TypeScript and SemVer] Me: [planning changes I’m going to make in August 2025 because I’m not allowed to make them before 6.0] 🤷
4
3
78
39,165
That went by quickly. I’ve been on the TypeScript team one year today. 😮
6
1
69
🌶️ Path aliases were added in 2015 to complement config for the RequireJS AMD module loader for the browser, popular at the time. If you’re using it in 2023 to create a resolution that doesn’t independently work at runtime, despite docs begging you not to, that might be a mistake
tsconfig path aliases were a mistake
13
6
75
42,522
The excitement for this is awesome to see. Big thanks to everyone giving it a try. A lot of people are asking why this isn’t the default Go To Definition behavior or if they can bind this to ctrl/cmd+click. The answer is probably too complicated for Twitter but let me try... 🧵
1
12
73
STOP DOING SYMBOL MERGING
8
10
70
Computer scientists clearly never looked at a tree in real life. Spoiler alert: the leaves are on the *top*
5
11
62
I wrote a @gatsbyjs syntax highlighting plugin that uses VS Code’s highlighting engine with its languages and themes, built-in or from any extension in the VS marketplace. Also has built-in OS dark mode support 😎 Let me know if you try it out! github.com/andrewbranch/gats…
3
12
63
arethetypeswrong.github.io now has links to full explainers on every problem kind detailing the symptoms users will see and common causes. Links to each can also be found on the README: github.com/arethetypeswrong/…
1
8
68
8,471
esbuild.github.io has the best design for an OSS tool: - Low noise, high text density - Marketing content is limited to half a page - Everything is just 5 long pages so you can ⌘F - Detailed site nav is always visible with no accordions or hovers (more ⌘F love) 👏❤️
4
65
12,169
Replying to @mattpocockuk
I’m working on a blog post that explains what’s going on under the hood with this! A deep-ish dive on symbols and declaration merging.
6
1
64
7,061
This is the first I’ve seen the timings from a profile in the code gutters. This is really cool.
2
6
58
💙 This is, I think, the *only* dual emit tool that provides the full strength of TypeScript’s checking for both output formats. Most tools do transformations they can’t guarantee and tsc can’t know about. This tool wraps tsc into a cleaner DX for dual building. Such good work 👏
I've seen people talking about how hard it is to ship TypeScript modules that work with both CommonJS and ESM. Indeed, it can be a dark art. I made a thing that makes it very simple: isaacs.github.io/tshy/
3
11
61
17,013
📢 New blog post (along with a visual refresh)! Featuring union signatures, contravariance, distributive conditional types, how to crash TypeScript 3.4, and not one but TWO hand-drawn pictures of an adorable rabbit! blog.andrewbran.ch/polymorph…
7
8
57
One obstacle to having a good experience with TypeScript is npm packages that have adopted ESM or new Node resolution features, but haven’t (or have incorrectly) updated their types. I’m throwing together a tool to identify those problems. Sneak peak: arethetypeswrong.github.io
6
8
57
9,291
7. (cont) @bluwyoo’s publint.dev is also great for the non-TS side of package validation. Thanks @alistaiir for being a good sport and providing an example of an issue I see pretty much every day ❤️ Ok, going back to the beach ☀️
8
4
60
8,727
Oh hey this release has some of my code in it, hope it works 🙃
Our release candidate of TypeScript 3.5 is now available with significant performance improvements! Please try it out and give us your feedback! devblogs.microsoft.com/types…
3
1
51
Deleted Twitter from my phone. I really like seeing what TypeScript stuff you all are talking about, and I even feel like that has a positive impact on my work, on the margins. But I waste more time than I need to. I’ll try to check notifications and DMs over lunch most days. ✌️
2
50
5,848
📣 A community member contributed a CLI for arethetypeswrong! 👏 Thanks so much to ej-shafran on GitHub! npmjs.com/package/@arethetyp…
1
10
47
14,204
1. `"type": "module"` makes Node interpret *.js files and makes TypeScript interpret *.js, *.ts, and *.d.ts files as ES modules. (Some bundlers respect/enforce this too.) For Node, this means `require` and `module` will be undefined, the file must use import/export syntax, and...
1
1
45
18,315
Replying to @DavidKPiano
/** @internal */ properties get stripped from declaration emit so you can use them but your users can’t, if that’s the goal?
2
45
3,790
💙 arethetypeswrong.github.io / @arethetypeswrong/cli now support checking a package against types from DefinitelyTyped. DT tooling doesn’t currently check for module format disagreements, so it would be nice to integrate this into PR checks.
1
4
44
6,209
Doesn’t feel like I’ve been working on TypeScript for four years. Hoping to finish that “What I Learned In A Year Of Working On TypeScript” blog post I’ve been thinking about by my 5-year mark
New things: I’m joining the #TypeScript team starting next week! Incredibly excited and grateful for the opportunity to work full-time on a product I love and use daily. So much to learn! 😍
2
41
4,287
Just noticed that yesterday I merged my 100th PR into @typescript 🤯 These nine months have gone by super fast!
1
40
This isn’t wrong per se, but I feel like some people (not Matteo) assume the absence of *guarantees* about breaks means TypeScript and DefinitelyTyped will indiscriminately merge anything at any time. We are typically not, in fact, trying to break your builds just for funsies
Devs: we want the safety of TypeScript TS: every minor might include breaking change DefinitelyTyped: every release might include breaking changes Module authors: it's okay to ship breaking changes to types in minor releases Developers: your minor update broke our build!
5
3
41
14,920
Thoughts about how applicable this advice is to libraries: blog.andrewbran.ch/is-nodene… Thanks @mattpocockuk and @tpillard for the discussion.
A quick visual guide on the only two valid settings for module/moduleResolution in TypeScript. When you're transpiling with tsc, use NodeNext. EVERY OTHER TIME, use ESNext/Bundler.
2
11
43
15,823
It finally came! If you are learning TypeScript, may I suggest Learning TypeScript. There’s so much TS content out there, it can be hard to tell the good from the bad. I’ll make it easy: this is the good. Herein @JoshuaKGoldberg not only says CORRECT FACTS but also GOOD OPINIONS!
2
2
35
Bundlers disagree about whether to replicate Node’s ESM/CJS interop in .mjs files. Webpack and esbuild do (and I support this approach) but it looks like they might be the only ones. What’s the right way? What should we encourage future bundlers to do? andrewbranch.github.io/inter…
3
6
42
11,291
3. AFAIK `module` is something bundlers made up and we should consider it superseded by `exports`. Node does not use it; TypeScript does not use it. I think we should stop using it if possible since it adds noise to a noisy space.
3
41
12,765
Today is a “Learning Day” at work, so instead of going to meetings and working on TypeScript, I bought @thorstenball’s compiler book and am going to learn about bytecode and VMs. Super excited!
1
2
30
Five years ago today, I finished backpacking from Georgia to Maine on the Appalachian Trail. Kinda miss it!
2
1
29
Apparently 15% of #TypeScript issues I’ve closed since joining the team (in April) have been fixes/improvements related to auto imports. I wonder if it’s a noticeable difference to a typical user, or if it’s just a bunch of edge cases that make a big difference to a few people?
6
4
29
This is maybe the first time I’ve seen the replies to a tweet bemoaning something about ESM lean more toward “actually this is good” than “ESM is a disaster.” Maybe we’re reaching a turning point.
So like, we're all just ok that ESM requires you to include the extension of the module you're importing? 😩
1
1
35
6,109
So many snarky takes about this. TypeScript is 11 years old and this syntax predates the existence of ESM. The reason it’s not just var/let/const is those can’t declare a type: const Foo = require("foo") const f = new Foo() // ok const g: Foo = f // Cannot use 'Foo' as a type
HOW did I not know this syntax existed? This gives you full type safety with require in TypeScript. Feeling like a prize idiot.
2
4
33
9,904
When a user reports arethetypeswrong.github.io errors to a package author, I’m always nervous how they’ll respond. But the last several interactions I’ve been pinged on have been super positive 💙 Congrats on an improved date-fns release! So happy folks are finding attw useful 😊
Good news: I just shipped date-fns@3.0.0-alpha.2 with improved types. Now it's all green on arethetypeswrong! Thanks to @karlhorky and @atcb for pointing me to the problem. The bad news is that I forgot `--tag next`, so now it's the latest release 🫠
4
3
32
6,562
Secondly, modules is a triggering topic, and some disagree with decisions TS has made. 99% of people are capable of doing so respectfully. I think I have a resasonably healthy level of emotional distance from my work, but prolonged exposure to the negativity takes a toll. 3/5
1
32
2,515
Who wants to buy this T-shirt?
3
2
32
The 172 hardest problems in computer science are cache invalidation, naming things, and off-by-169 errors
1
29
I’m excited, but unexpectedly nervous to have this out. For one, I’ve spent so long with it, it’s approaching the point of semantic satiation for me. I can’t trust my own judgment of the quality of the content anymore. 2/5
1
1
30
2,635
VS @code Insiders debugger now lets you jump backwards to the beginning of a function 🤯
2
9
31
New blog infrastructure → first blog post in 3.5 years blog.andrewbran.ch/new-blog
4
2
32
4,652
Ok, the types are wrong, but are they getting less wrong over time? I’m not sure yet, but I just published a JSON file with 17,041 arethetypeswrong runs of the top npm packages from the 1st of every month since Jan 2022, so I should be able to find out. npmjs.com/package/@arethetyp…
2
3
29
7,575
Just noticed another thing @Netlify currently does better than CloudFront: gzips WASM automatically. I had a to-do item to automate compression on my end before uploading to S3... 😱🙅🏻‍♂️
1
4
29
.@1Password’s “password history” feature just saved me while updating an expired password in a form that didn’t submit correctly. Don’t know if that’s a new feature in 7, but either way, I love this app more every day ❤️
3
22
🧑‍💻 2014: I have 17 JS files, how do I turn them into just one? 🧑‍💻 2022: I have 17 bundlers, how do I quit JavaScript
Doing an audit of module resolution features in popular runtimes and bundlers. What should I add to this list? - Node <= 10 - Node >= 12 - Modern browsers - Deno - Webpack - Vite - esbuild - Parcel - Snowpack (Better yet, does a nice table of these already exist somewhere?)
2
2
29
arethetypeswrong.github.io can now recognize types that incorrectly use `export default` when they should use `export =` (which is the most common module typing mistake I see). This analysis has limitations, but I bet it’s usually right. Let me know if you see a weird result.
2
3
31
13,329
A common thread in TS module confusion I’ve seen is a missing/incorrect mental model of how the compiler “thinks” about modules. I hope these docs build a shared understanding of what we’re doing here, even if you don’t like it, so we can start conversations on the same page. 4/5
1
1
29
4,466
1. (cont) Big picture: `"type": "module"` does not make an ESM package—there’s no such thing; CJS/ESM is determined per-file—and there is another way to make ESM files. `"type"` just changes the interpretation of the kind-ambiguous extensions.
1
2
29
16,970
1. (cont) The presence or absence of `"type": "module"` can always be overridden on a per-file basis by changing its extension to the module-kind-specific variant, i.e. .cjs/.cts/.mjs/.mts. The only difference to be aware of is that you can’t use extensionless imports...
1
29
16,572
2. `main` will not be processed by anyone who understands `exports` if `exports` exists. Probably wise to keep it around for good back compat, but Node versions who need it are all EOL.
1
28
13,313
I made a blog where all the code samples are interactive. You can see type information and compiler errors and even edit the code, if you want. Built with #React and #TypeScript, my first post is about (you guessed it) React and TypeScript. Enjoy! blog.andrewbran.ch/expressiv…
6
10
25
5. (cont) My advice is not to use `types` at all, and instead let extension matching do its work. There needs to be a dist/index.d.cjs file present. After that, you can delete `types` (both in `exports` and at top level!) and everything is perfect.
2
26
18,439
✅ This wouldn't be a breaking change in existing TypeScript/JavaScript code ✅ This wouldn't change the runtime behavior of existing JavaScript code ✅ This feature would agree with the rest of TypeScript's Design Goals ⬜️ This is not a duplicate of #9998
3
1
25
Replying to @evanyou
I would love to see first-class .d.ts emit/bundling as part of this. Rollup makes it too easy to make libraries with broken typings because of a lack of symmetry between ts→js and ts→d.ts transforms. Want to chat with me / the team? 😃
3
26
5,035
Replying to @SeaRyanC
Sounds like that will pair nicely with mine, “The most popular TypeScript features I’ve worked on, and why you shouldn’t use them”
2
23
987
This was such a fun conversation! Make sure to check out the rest of MiTS’s videos too. They just wrapped up a series of challenges showcasing some truly bananas TypeScript wizardry.
We sat down with @atcb from the @typescript team to discuss AreTheTypesWrong, a project that analyzes npm package contents for issues with their TypeScript types, particularly ESM-related module resolution issues. piped.video/watch?v=8pOi1ccd…
2
2
25
7,715
Replying to @mattpocockuk
Yes, this Rust code is completely invalid syntax
1
24
2,707
Ok still no but I respect the effort
3
1
25
5,729
Replying to @mattpocockuk
The type space absolute value operator, even though it doesn’t work too well 🤪
4
24
3,198
An update on Go To Source Definition. In VS Code Nightly, you can now replace Go To Definition with Go To Source Definition with a preference, allowing you to ctrl-click / ⌘-click and use the default F12 keyboard shortcut.
The excitement for this is awesome to see. Big thanks to everyone giving it a try. A lot of people are asking why this isn’t the default Go To Definition behavior or if they can bind this to ctrl/cmd+click. The answer is probably too complicated for Twitter but let me try... 🧵
1
5
25
5,038
These packages fixed FalseCJS/FalseESM since April: tslib (😅) commander acorn postcss is-what copy-anything helmet msgpackr csv dexie Nice work! 💙 I haven’t gone and looked, but does anyone know anything about the fixes for any of these? Love to see a success story play out.
Ok, the types are wrong, but are they getting less wrong over time? I’m not sure yet, but I just published a JSON file with 17,041 arethetypeswrong runs of the top npm packages from the 1st of every month since Jan 2022, so I should be able to find out. npmjs.com/package/@arethetyp…
4
23
3,422
“Misery resolution algorithm” is perhaps the best typo—dare I say Freudian slip?—I have ever seen
Replying to @robpalmer2 @atcb
There are two parts to the misery resolution algorithm: the order we look for directories, and the extensions we use to lookup files. For directory orders, all algorithms conform to the node.js spec. For extension lookups, bundlers need their own rules, hence the current mess.
2
1
26
5,497
I’m not very good at self promoting, so I guess I would be remiss not to RT someone else promoting me 😄
Replying to @orta @swyx @typescript
wtf this is the coolest blog I’ve ever seen. The tooltip with typescript info is 🔥github.com/andrewbranch/blog…
1
2
21
Takeaway: do not skip .d.ts emit if you care about your users’ DX, even in a world where all your users can consume TS directly.
2
3
27
4,993
Real question: who exactly is being served by dual ESM/CJS npm packages? I want the ecosystem to move to ESM, but if you need to ship CJS for compat right now, I understand. But then, why ship both? (Please don’t tell me ESM is more tree-shakable without citing your sources.)
12
25
7,392
I’m super excited to be speaking about arethetypeswrong.github.io at #TSCongress. You can register and watch the live stream for free :) See you September 21 & 22! (My badge seems to have a random snippet from my conference bio, and it’s... too perfect 😂) portal.gitnation.org/badges/…
1
4
25
2,276
A kickstarter I backed that’s ~2 years overdue on fulfillment has just informed me that COVID-19 is impacting their ability to deliver 🤨
2
21
Overheard at @microsoft today: “Your team is in charge of accessibility for [product], right?” “Everyone is in charge of accessibility.” 👏🏼👏🏼👏🏼
2
1
15
6. (cont) There are surely valid scenarios to ship just CJS or just ESM. I don’t recommend the former because I think a full transition of the ecosystem to ESM is inevitable and an eventual good, with significant growing pains...
1
23
7,510
Can 12 people please unstar #TypeScript so I can get a screenshot without cheating
Nooooo I missed it!
4
18
With apologies to @drosenwasser: How Twitter renders a link preview for the TypeScript 4.8 blog post vs. how Microsoft Teams renders it... 🤔
3
23
Some folks will like this because it enforces using type-only imports wherever possible. But the effect I’m most excited about is it makes it really obvious whether you’re writing an ES module or CJS module. 🧵
Typescript treats 😉 Congrats to @atcb on landing the new "verbatimModuleSyntax" option in @typescript heading for TypeScript 5.0 🎉 This simplifies how TS import statements are compiled to JS. Only the parts of the import marked with `type` get erased. github.com/microsoft/TypeScr…
1
2
22
5,540
“We are excited to introduce a new module resolution setting, named with input from the community: `BundlyMcBundlerface`”
2
2
23
I decided to go with the second option 📷 Paul Carr
It’s sad (though personally reassuring that I’m not just a particularly unlikeable communicator) that Matt is getting the same level of outrage as I get when I explain it. So should I reply to every comment or maybe it’s time for a vacation
5
21
5,976
You know, the way you usually start a sentence
3
21
1. (cont) import paths must use file extensions. (TypeScript applies the same rules to .ts files so stuff works when you compile to .js and run in Node, and to .d.ts files because that extension represents a *.js file by the same basename, which will be subject to said rules.)
1
21
17,296
Replying to @mattpocockuk
There’s one thing in this explanation that I think needs to be clarified. You’re calling .ts/.tsx files “modules” and say .d.ts files are for global scope augmentations and are not modules. This isn’t quite right. Moduleyness vs. scriptiness is orthogonal to .ts vs .d.ts.
2
21
1,601
.d.ts / .ts Files: 268 / 317 LOC: 49k / 62k Instantiations: 11k / 46k ❗ Memory: 92 kB / 118 kB Parse time: .76 s / .91 s Check time: 1.48 s / 3.02 s ❗ Total time: 2.58 s / 4.43 s ❗
2
23
2,856
4. `type` is an override to tell TypeScript where the types for `main` are. Without it, it will look for a declaration file next to `main` with identical basename and corresponding extension—but not in resolution modes that respect `exports`, so it doesn’t really matter here.
3
21
12,777
Seeing this take a lot but don’t quite understand how a runtime making different interop choices from the most popular runtime is going to change the landscape, unless the implied premise is that Node.js usage drops to near-zero 🤨. Libraries will have to support both, no?
if bun actually frees us from ESM/CommonJS hell then that might be its killer feature
8
1
21
9,591
Lorem oopsum (n.) - When you forget to remove clever or inappropriate placeholder text from a product before a demo or a release.
5
13
📝 New blog post covering tips on debugging the TypeScript codebase. Thanks @JoshuaKGoldberg for requesting this topic! blog.andrewbran.ch/debugging…
2
21