New post/talk: Javascript's superpower: linting
-
Start with meetup advertising: DomCode starts their meetups with their strict anti-harassment policy: don't harass people over gender, sexual orientation, choice of programming language, vim vs. emacs, tabs vs spaces, PHP vs everything else....
-
I love it: it's a funny way to emphasise a friendly atmosphere.
-
It takes a jab at this stereotype about engineers. Of course it's a stereotype, so it doesn't always hold, but... It always holds.
-
There's also this other stereotype about engineers: if we encounter a problem, we'll solve it with technology.
-
Ergo: linters! No more arguing about tabs vs. spaces, we'll simply have this tool that will analyse your code to check whether it matches certain rules. If it does, it exits OK, if not... It'll BREAK YOUR BUILD, HALT YOUR COMMIT, OR SCREAM IN YOUR FACE TO FIX IT.
-
Today, many people use eslint for this in Javascript-land. (Hands?) But it's actually the third generation of linters.
-
The first linter came with a book - or rather the other way around.
-
This book was written at a time when nobody really took Javascript seriously. Webpages were mostly HTML and CSS, sometimes generated by a back-end in e.g. PHP, and you'd have the odd
on-click
handler here and there, or a fancy clock following your cursor that you'd downloaded at some shady website. -
But not Douglas Crockford. Crockford said that, if you restrict yourself to a subset of Javascript, it's actually a pretty nice language with some interesting features. For example, because it had functions as first-class citizens (you can pass them around without executing them), he argued that it was actually closer to a language like Haskell than it is to Java.
-
So he wrote a book. It's called "Javascript: the good parts" and I'd highly recommend it - it's what got me started with Javascript proper. And it's not even that big.
-
Anyway, he wrote a tool called JSLint, that analysed your code, and warned you of using things outside of that subset.
-
Fun fact: the term lint is "derived from the name of the undesirable bits of fiber and fluff found in sheep's wool". There's actually an entire Wikipedia page on it, including a picture of a man's navel in which lint "naturally accumulates". I'll spare you that; here's a picture of lint in a pocket.
-
So... JSLint was great, but rather opinionated - Douglas Crockford has strong opinions. People didn't like that, so they made a version of JSLint that has some options, like... Whether you'd like to use tabs or spaces? Or perhaps some combination of the two following strict rules? It was called JSHint.
-
But you were limited to options the JSHint programmers made available, so someone came up with ESLint. You could now write your own completely custom rules and plug them in! If you wanted a rule that enforced every variable name to use the suffix
-Smurf
, you could! -
And obviously people took a bunch of those rules and packaged them together in a highly opinionated unconfigurable set, and called that Standard JS. But I digress.
-
I would argue that linting is what "saved" Javascript. The mantra of everyone that makes standards for the web is: Don't break the web. In other words: you can never remove features. What you can do, though, is add them. So TC39, that Javascript standards body, just added new things like
let
andconst
, we'd set up ESLint to tell us not to usevar
, and boom! It's like you're using an entirely different language. -
But anyway, the point here: ESLint catches bugs even before you run your code for the first time.
-
Example in which I create a
<span id="name"></span>
, which should show the name someone is typing in a form field - but because I "forget" declaring the variable (i.e.let name
), it actually refers towindow.name
which is the element with that ID. -
So ESLint would actually tell me about it. Great!
-
Obviously ESLint can't catch all bugs.
-
Example in which I forget to
await
a Promise. -
But: we can do better!
-
Run TypeScript on plain Javascript file do demo what errors it can catch through inferring.
-
Example in which I add my own type hints.
-
People's fear was CoffeeScript: entirely different codebase for some syntactic sugar that's now in Javascript proper. Legacy!
-
But TypeScript is just Javascript (show output of compiled code).
-
Other worry: more tooling!
-
Yes, serious downside. Especially if you're not using any now. But: most of us use a linter.
-
Does that mean Babel now replaces TypeScript? No.
-
But: it can convert TS to plain Javascript. Example: compile the previous example with Babel.
-
So what does this mean? If you use Babel, you can keep using it while adding type annotations. No changes in build pipeline, the code you deliver to users, etc.
-
But: you can use TypeScript as an advanced linter now!
-
That means the ecosystem is really good now. Angular has been using TypeScript since forever, React was already using Babel so ships it by default with CRA now, Vue supports TypeScript and is being rewritten in it, so framework-wise, we're pretty good.
-
Many packages ship their own type definitions, and practically every large library has
@types/
packages available. -
So when to use: if you already (are planning to) have a build pipeline, especially if you're using Babel, are not using risky unknown libraries that have no typings, and only for new code.