Rule proposal: no-null (revisited)
See original GitHub issueLet’s reopen the discussion https://github.com/eslint/eslint/issues/6701 regarding adding a no-null
rule as part of ESLint core.
Currently this is solved by eslint-plugin-no-null, however it’s awkward to rely on an external NPM package for such a simple and basic rule.
The previous issue was closed with the opinion:
To me this seems like a very personal preference, so I’m 👎 on inclusion in the core. This would be better as a custom rule.
I’d like to offer some counterpoints:
- ESLint announced that it would be replacing TSLint, which provided no-null-keyword as a core rule. Thus, this is a gap for people migrating from TSLint.
- When I worked at Microsoft, hundreds of projects used TSLint to forbid
null
- Now I work at HBO, and they apply this rule in a massive internal monorepo
Thus, this practice is at least somewhat mainstream. Why is that? (The next section is optional reading heheh.)
Why forbid null
instead of undefined
?
Most programming languages have a “null” or “nil” value that functions…
- as the initial value for an uninitialized variable; and
- as the value of
x.y
orx["y"]
when x has no such key; and - as a special token that developers can assign to indicate an unknown or empty state.
In JavaScript, the undefined
value fulfills roles (1), (2) and (3). JavaScript’s null
value is a redundant secondary token that can only be used for (3), even though its name confusingly implies otherwise. From this perspective, the null
value was arguably a mistake in the original JavaScript language design. Nearly all other programming languages get along just fine with a single “null”/“nil” concept. In actual practice, JavaScript loses no expressiveness if we always write undefined
instead of null
.
One potential hitch is external libraries such as JSON.parse("null")
and some popular NPM packages that return null
from their APIs. However, if we relax the lint rule to allow null
comparisons, these cases rarely produce lint errors.
By contrast, banning undefined
values would be impossible, since null
cannot satisfy the roles (1) and (2).
Of course, it’s completely valid to use null
and undefined
together. But this practice requires developers to keep two concepts straight in their heads. In TypeScript, it sometimes requires clunky type annotations like string | null | undefined
. Thus while using null
is valid, and perhaps more historically idiomatic, it adds complexity without providing any significant value.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:9
- Comments:6 (3 by maintainers)
Top GitHub Comments
Just as a note, I think this can currently be achieved with
no-restricted-syntax
with selector"Literal[raw='null']"
. Here’s a demo.Hi everyone - A while ago the ESLint team made the decision that we would no longer be adding new core rules that simply disallowed some syntax. The primary reason for this is we knew if we continued down that road then everyone would want a rule to specifically disallow their least favorite syntax and we’d end up with hundreds of rules just for that. When we heard feedback that people didn’t want to have to manually create and maintain their own plugins for just one rule, we added the
no-restricted-syntax
rule, which would allow anyone to define syntax they wanted to disallow.Discussions about whether or not
null
orundefined
is more preferred in any particular segment of the JavaScript community don’t really weigh into the decision here. Given that we have nearly 300 rules already, the bar for adding any new rule is particularly high, and this proposal doesn’t qualify.Just to review, if you want a rule to disallow
null
, you do have several options:eslint-plugin-no-null
packageno-restricted-syntax
to get the same behavior with an existing core ruleGiven that the first two options don’t require any work, they both seem like good approaches.
Thanks for the suggestion. We do appreciate thoughtful proposals like this one even though we aren’t always able to accommodate.