It started with a small TypeScript issue.
I came across a problem in TypeScript regarding an incorrect DOM type and decided to fix it. I thought it would be a straightforward task: find the issue, make a change, open a pull request, and move on.
Instead, I fell into a deep rabbit hole.
I began exploring how TypeScript's browser APIs are generated, how web standards work, and how browsers, specifications, and TypeScript interact. What began as a fix for one incorrect type turned into months of contributing to the TypeScript DOM generator.
Little by little, I became more familiar with the project. I discovered edge cases, addressed missing elements, improved definitions, and learned about the connection between web specifications and the TypeScript types that millions of developers use daily.
What is the TypeScript DOM generator?
If you've ever written TypeScript for a browser project, you've likely used APIs like:
document.querySelector("button");
window.localStorage;
fetch("https://example.com");
These types don't just appear out of nowhere. They come from a generated file called lib.dom.d.ts.
The TypeScript DOM generator is the tool responsible for creating that file.
Instead of writing thousands of browser API definitions by hand, it pulls information from web standards and generates TypeScript declarations.
In simpler terms:
Web standards
↓
TypeScript DOM lib generator
↓
lib.dom.d.ts
↓
TypeScript IntelliSense and type checking
This tool serves as the bridge between the browser platform and the TypeScript developer experience.
Falling into the web standards world
While working on TypeScript's DOM generator, I began to learn about topics I had never needed to understand before.
I learned about:
- Web IDL
- W3C specifications
- WHATWG standards
- Browser engines like Blink and Gecko
- How browser APIs are defined and implemented
Before this, I used browser APIs daily without considering their origins.
Understanding the process behind them changed my perspective on frontend development.
A browser API is not just a function you call. There is an entire process behind it:
Specification
↓
Browser implementation
↓
Documentation
↓
Type definitions
↓
Developer experience
The documentation problem
On March 14, 2025, I had an idea.
The TypeScript DOM generator had an outdated apiDescriptions.json file containing API documentation, but it had not been maintained for years.
The issue was that browser APIs constantly evolve. New APIs are added, existing APIs change, and documentation is updated.
I thought:
"Why should TypeScript have outdated API descriptions when MDN already provides documentation for these APIs?"
So, I opened issue #1937:
https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1937
After discussing the idea with the maintainer, Kagami Sascha Rosylight, who works on browser standards with Mozilla and WHATWG, I received the green light to proceed.
Building the documentation generator
On March 15, 2025, I submitted my first pull request for this issue.
The goal was straightforward:
Take documentation from MDN and automatically add it to the generated DOM API definitions.
The final implementation was more complex than my initial idea.
I had to address:
- Matching MDN documentation with TypeScript DOM APIs
- Handling APIs that lacked documentation
- Generating correct JSDoc comments
- Integrating with the existing generator pipeline
- Ensuring the generated output remained consistent
The final implementation added over 7,000 lines of code, along with a small file of around 112 lines that managed the core documentation generation logic.
That file underwent more than a month of iterations, discussions, and improvements.
Interestingly, the final solution was not enormous. The challenge lay in understanding the ecosystem surrounding it.
A small piece of code can require extensive investigation when it becomes part of a project used by millions of developers.
The pull request journey
Open source is not just about writing code and getting it merged.
The process included:
- Discussions with maintainers
- Reviewing feedback
- Changing the approach
- Improving edge cases
- Adapting the solution to fit the existing architecture
Each review helped me understand the project better.
The goal was not only to get the code to work but to ensure it could integrate into a long-term project.
The merge
After weeks of effort, the pull request was finally merged on April 17, 2025.
It also happened to be one day before my birthday, which made it even more memorable.
Watching something I contributed to become part of TypeScript's ecosystem was an incredible experience.
The unexpected surprise
Later that month, I found out that Microsoft mentioned my work in an official TypeScript blog post about TypeScript 5.9:
I was also mentioned by Theo in one of his videos discussing the update.
What began as a small issue about an incorrect type turned into a contribution that enhanced the experience for developers using TypeScript every day.
What I learned
This experience taught me several things:
Read the code behind the tools you use
Most developers use TypeScript daily without thinking about how its types are formed.
Looking deeper revealed an entire world behind something I previously took for granted.
Specifications matter
Learning about web standards reshaped my approach to frontend development.
The web relies on specifications, and understanding them clarifies the platform itself.
Small contributions can turn into big opportunities
I did not set out to make a sizable contribution.
I began by addressing one issue.
Curiosity led me to another issue, and eventually to a much larger project.
Open source is collaboration
The best part was not just writing code. It was working with maintainers, receiving feedback, and refining the solution together.
A small TypeScript issue introduced me to web standards, browser APIs, and the inner workings of one of the most important tools in the JavaScript ecosystem.
And it all began with a simple question:
"Why is this type incorrect?"
Special Thanks
I would like to thank everyone who helped me throughout this contribution:
- Kagami Sascha Rosylight for reviewing my ideas, discussions around the implementation, and helping guide the direction of the project.
- Jake Bailey for his guidance and feedback during the contribution process.
- Nathan Shively-Sanders for his feedback and insights from the TypeScript compiler side.
Open source projects are built by communities, and this contribution would not have been possible without the time and feedback from maintainers and contributors.
Top comments (0)