Howdy! This blog post talks about the historical context around migrating from TSLint to ESLint. 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.
Before we talk about today’s solutions for linters, let’s talk a bit about the necessary vocabulary.
- Linters are programs that scan source code for common logic and style complaints.
It was able to complain about basic style preferences such as odd whitespace amounts or where you declared your
=== instead of
==, …and not much more.
There were no hooks for your own rules or configuring the checks outside of code comments.
Recall that Prettier, which still isn’t adopted by all major companies and teams (😡), wouldn’t be released for another 15 years. Getting stubborn developers to agree to use a nonconfigurable tool for style complaints was even more difficult back in 2002 than it is now.
The Prettier One Year Anniversary blog post is a great summary of how those kinds of projects have grown over the last few years.
Fast forward to 2011 and JSLint was still not a particularly appreciated tool - in large part because of its extreme configuration rigidity. A configurable fork of JSLint named JSHint was released in 2011 by Anton Kovalyov, sparking a good deal more interest in the linting space. See Anton’s Explanatory Blog Post for more on the historical context behind forking to JSHint.
Although it was more configurable, JSHint still had a rigid, older codebase, and did not yet support user-written rules. You were still stuck with the default set. Yuck.
2013 saw the initial release of ESLint by Nicholas C. Zakas. What a tool! ESLint got right what JSLint and JSHint struggled with from the start - a skeleton core with separate, pluggable rules in and out of the base project. Its API allowed community-recommended configurations such as the Airbnb config.
See the ESLint introduction post for some amusing discussions around ESLint’s creation:
“And so I somewhat regrettably introduce ESLint”- Nicholas C. Zakas, 2013
Developers at Palantir, a tech company with an interesting reputation, released an equivalent tool to ESHint/ESLint named TSLint in 2013 to go along with the then-fledgling TypeScript.
On the bright side, TSLint gained the ability to use TypeScript’s type checking APIs in 2015! That allowed for a new, powerful class of rules that could use TypeScript types in addition to basic syntax for their checking.
On the surface, the tooling upgrade that enabled for killing off TSLint was when ESLint gained the ability to lint syntax extensions. We can now write plugins such as typescript-eslint for ESLint to run on TypeScript and other non-standard languages.
TSLint’s true killer was the TypeScript team itself announcing a switch from TSLint to ESLint support in late 2018. Palantir announced TSLint’s deprecation plans in a blog post the next month along with a deprecation plan on the GitHub TSLint issue tracker.
There’s no question about it: TSLint is dead. Long live ESLint.
The death of TSLint is a fascinating thing. Although the TypeScript switching to ESLint was the surface killer, I like to think there were a few communal issues that helped contribute to its lower community involvement.
You could also blame, in part, the difficulties of promoting open source in a for-profit organization. TSLint went mostly or partially unmaintained for long periods several times through 2017 and 2018.
Did one or two of these maintenance issues cause the others? Was there one clear cause of decay, or a vicious cycle of community bleeding? If Clinton had defeated Trump and eased up on ICE raids, would we be talking about merging ESLint into a community-run TSLint?
We might have seem a more difficult transition from a more fully-featured TSLint to ESLint, but that’s all conjecture. Ultimately we’ll never know.
By now I hope you understand why TSLint is moving over for ESLint with typescript-eslint, and if you still use TSLint, you have some energy to spend migrating over.
I wrote a cute little tool called tslint-to-eslint-config that generates an ESLint configuration using your existing TSLint configuration. Maybe it’ll be useful for you! See the next post in this series for an overview of how it works.
Thanks for reading this far — happy linting!