Howdy! This blog post is a personal reflection on my experiences working with TSLint. If you’re curious about TSLint’s history, go back to TSLint to ESLint Part 1: Historical Context. If you just want to understand how tslint-to-eslint-config migrates configurations from TSLint to ESLint with @typescript-eslint, skip to TSLint to ESLint Part 2: tslint-to-eslint-config.
I joined the TSLint maintenance team in November 2018, at the peak of its disrepair. No other maintainers were active and the library hadn’t been updated in quite a while. My first goal was to sludge through the hundreds of unaddressed or stale issues and pull requests.
But Why Bother In The First Place?
Back in 2018 it wasn’t clear (at least to me) what was going on with typescript-eslint. I wasn’t sure it would achieve feature parity with TSLint’s typed rules in a performant manner to run with ESLint.
Now it’s obvious I was wrong. I was very wrong. I was incredibly, obviously, plainly wrong.
But, still, in 2018 the commonly accepted way to lint TypeScript code using rules that had access to the type checker was with TSLint.
Which had 20 pages of untriaged issues and 70 pull requests left open.
Which was still recommended by many as “the” TypeScript linter despite having an objectively inferior architecture to the relatively obscure fimbullinter/wotan.
Which was a project I’d used to great effect in my personal and work projects — that I could see had incredible potential for improving developers’ TypeScript code.
What Is and What Should Never Be
My longer-term goal after joining TSLint would have been to move it towards a community management team. That would have helped buffer TSLint from fluctuating attention on the Palantir side (though I’m sure the developers there would have continued to play a big part in contributing!), and helped bring in the developer power to catch up to ESLint.
We’ll never know what that would have been like now. TypeScript announced its switch of focus to ESLint a couple of months after I started on TSLint. As exciting as it was to take on maintaining TSLint, it was even more exciting to see the plans to switch to ESLint.
Was It Worth It?
Yeah! Of course!
I wanted to step up and make the (linting) world a better place. I think I objectively did. We did — through plenty of people, including other maintainers and hundreds of contributors.
We helped keep a lot of TypeScript projects linted until typescript-eslint was ready. Mathematically, if thousands upon thousands of projects were using TSLint, and TSLint was able to catch issues ESLint was not, we must have prevented thousands upon thousands of bugs. I’m so immensely happy with and proud of the work that was done on TSLint over its few years.
Being a Maintainer Rocks
TSLint was the third community-visible open source project used and contributed to by others I was truly a ‘maintainer’ on (my own, now-DMCAd FullScreenMario doesn’t quite count). My first two were TSLint.MSBuild and tslint-microsoft-contrib. You could say that TSLint was and is the backbone of my nascent open source maintenance experience. Helping steer these projects is a fantastic learning experience and a wonderful way to give back to the community — even with all the turmoil and shenanigans. I’m eternally grateful to the folks in and out of TSLint’s maintenance team for giving me the chance to work on TSLint.
I would highly recommend doing maintenance work in open source if you ever get the chance. At the very least, it helped teach me:
- How to document long-term architectural decisions and goals when project ownership isn’t clear…
- How to file clear, understandable issues for newcomers with little-to-no project context…
- The importance of lowering barriers to entry for contribution: e.g. autoformatters, tests-as-documentation, and getting started guides…
- The true, incredible power of requiring filled-out issue and pull request templates…
…and most importantly, that open source management is a two-way exchange. Managing a project needs empathy and understanding from both ends. Maintainers need to understand how users use the project, so they can set up new users for success and empathetically respond to issues and pull requests. Users need to understand the reasons behind maintainer decisions so they can work with the system as they’re improving it.
Maintainers ideally set up processes to allow these streams of information to flow freely and share information as necessary. Users ideally work within those streams to contribute meaningfully. Ideally, everybody plays nice and understands that both sides want what’s best for everyone.
Being a Maintainer Sucks
Yet, open source software is built over the internet. Do you know what type of people inhabit the internet?
I’ll admit I made mistakes and was the “asshole” plenty of times throughout my maintenance tenure:
- I merged a PR that duplicated another person’s work.
- I got into debates without explaining my context or over unnecessary esoteric features.
- I closed issues prematurely.
- I added rules and features without documenting them well, causing headaches for beginner and advanced users.
- I indicated a big refactor would be accepted even though we didn’t have the maintenance staffing to support it.
Taking on maintenance for a project (hopefully) means you care about where it goes: you want it and its users to be made more productive by the time you spend on it. I took on a real emotional weight by committing to spending personal time on TSLint. We can talk all we want about work/life balance and how volunteer work should be a pleasant experience and how open source should be a golden utopia of working towards common goals… but at the end of the day, many projects are free labor provided out of some feeling of commitment and goodwill.
All this is to say: spending time maintaining a project can truly open you up, emotionally, to an inevitable cesspool of internet rage. You feel responsible for every “why isn’t this working?” or “please, this feature is necessary!” or -the worst of them all- “why isn’t this done yet?”. Issues pile up when you take a break. Eventually every spare moment in your schedule is a choice between improving the lives of internet strangers and improving your own.
Maintenance is a goddamn burden if you let it be.
Embracing the Asshole
One insidious change I noticed in myself was a growing disregard for the plight of users. GitHub activity from users meant more work for me - why would I want more of them? My initial enthusiasm for the project matured into a stoic sense of duty, which eventually soured into a sludgy reluctance to do more than the bare minimum of contribution work. My issue responses accordingly went from supportive paragraphs of prose in late 2018 to curt MVPs in mid-2019.
Again, if you have the chance to maintain a project, I’d highly recommend you do it. But don’t go overboard — don’t let it be a significant portion of your life unless you’re ready to manage significant emotional balancing. Maintainer burnout is a real issue you need to pay attention to in yourself and on your projects.
Eventually I’d like to take on more responsibilities in the community again. But it’ll be a while before I’m ready.
If you haven’t yet, read Henry Zhu’s Open Source of Anxiety post. I only experienced a sliver of burden; maintainers of massive projects such as Babel have infinitely more to deal with.
I spent some time looking back through my GitHub activity in the various TSLint-related repositories. A few names stuck out as consistent supporters of me, the project, and/or the community.
Adi Dahiya is an obvious MVP here, as the only other active TSLint maintainer in 2019 — despite switching to studying a completely separate education track! Adi was involved in the project early on and, through PR reviews, helped me understand how to play in the TSLint arena. Additional shouting-out belongs here for spot-checking my early work as a maintainer and helping keep me on track while I figured out what I was doing.
Jason Killian was similarly helpful back in the day, and has since gone on to help run the ever-interesting TypeScriptNYC meetup. My first substantial TSLint PR back in April of 2016 involved a perfectly informational technical discussion with Jason.
Klaus Meinhardt is a tour de force: both by creating the
tslint-consistent-codestyle community ruleset and absurdly useful
tsutils, and the wonderfully crafted and themed fimbullinter/wotan.
Klaus never failed to give sound technical advice in my (often poorly thought out) TSLint pull requests while still a TSLint maintainer — and more recently, even in TypeScript.
I never did end up working with Noah Chen or Andy Hanson either, but enjoyed a solid period of helpful PR reviews from them in 2017. Sometimes I wonder what it would be like to have worked with Ashwin R, who originally created TSLint.
Hamlet D’Arcy did super work in setting up tslint-microsoft-contrib as the go-to place for non-core TSLint rules, and was kind enough to add me as a contributor earlier in 2018.
Andrii Dieiev came out of nowhere later on and helped support and eventually maintain the library as well. Beyond general maintainership, Andrii did a particularly great job on improvements to its build and release processes.
I’m sad we won’t be able to work on tslint-microsoft-contrib more. Much of my maintenance style in TSLint was developed in tslint-microsoft-contrib. For every way that TSLint itself was formalized and made for community standards, tslint-microsoft-contrib was the fun side plaything.