eslint: eqeqeq rule allow-undefined
What rule do you want to change?
Require === and !== (eqeqeq) https://eslint.org/docs/rules/eqeqeq#allow-null
Does this change cause the rule to produce more or fewer warnings?
In ECMA262:
null value is primitive value that represents the intentional absence of any object value.
undefined value is primitive value used when a variable has not been assigned a value.
In TypeScript team coding guidelines:
Use undefined. Do not use null.
https://github.com/microsoft/TypeScript/wiki/Coding-guidelines#null-and-undefined
So i think comparing with the undefined literal should also can be allowed.
How will the change be implemented? (New option, new default behavior, etc.)? Please support allow-undefined.
Please provide some example code that this change will affect:
foo == null
foo == undefined
What does the rule currently do for this code?
foo == null // correct
foo == undefined // incorrect
What will the rule do after it’s changed?
foo == null // correct
foo == undefined // correct
Are you willing to submit a pull request to implement this change?
It’s my pleasure
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 5
- Comments: 26 (14 by maintainers)
I don’t think this change should be made in core for a few reasons:
Since this is purely stylistic, it falls under our new policy.
If you’re never using
null
, why not just usea === undefined
everywhere? It would be safer and more explicit. The way I read this guideline is that you should never usenull
to represent a null value for APIs you control. That doesn’t mean you wouldn’t have to usea === null
in your code, since there’s a good chance you’ll be interacting with someone else’s code (even if it’s just the Node builtin or DOM APIs) that may returnnull
.In the ECMA262 specification, [[Writable]] of
undefined
isfalse
. So i don’t think is problem to useundefined
in 2020.And most people use feature like ES Module and Class, they are always in strict mode. In strict mode will throw TypeError when
undefined = anything
.In the following url, Brendan Eich say in 2011/01/14 20:18:
Obviously, this is a bug that the author agreed.
@kaicataldo I never said i never using null, and If you’re never using undefined, why not just use a === null everywhere, why not ban
"null": "always" | "never" | "ignore"
option.@ljharb “it avalible to use undefined like
foo == undefined
” is not “i only useundefined
”,and it’s very inaccurate to misrepresent as if it is. That a few vocal industry personalities have said something is “utterly broken” does not mean that the wider community and ecosystem agree. Use of undefined is in no way contrary to JS.I agree with @SyMind,
== undefined
should be a permitted option, and indeed a recommended option. I don’t agree with @kaicataldo for the following reasons:== undefined
, just leave the option off — if you want to continue to use null against industry guidance it is up to you — or simply don’t use a linter.== undefined
to include testing for null, in the very few circumstances that null is returned, we can simply forget about null. See — Douglas Crockford - JS the Better Parts @ 30 minutesUndefined
cannot be removed from code because following TC39 committee decisions, it was selected as the preferred base value for JS, onlyundefined
triggers ES6 default parameters and defaults for object deconstruction. Null was essentially semi-deprecated.== undefined
. Plus this is already a rule, but a broken one as it makes absolutely no sense to allow== null
as an option and not== undefined
— illogical rules, even if stylistic, result in bugs. Thus even if this was stylistic, it is a correction of one that was already included.null
in my JS code and Why I banned null from my JS codeundefined
, it is a long standing rule of very bad programming. Attempting to prevent a minuscule number of reckless programmers from doing something they should not be doing is a weak argument. Besides, if one did redefineundefined
most code formatters, e.g. VS code, will indicate a change in color ofundefined
, thus you would have to be both reckless and unobservant. (If one wanted to, one could overwrite almost every prototype method in JS, but we don’t stop overriding prototypes in EsLint.)null
is to allow== undefined
because many external API calls return null, as doesstring.match()
and several other edge cases. By not allowing== undefined
it forces the continued use of null throughout code, which is confusing, confusion means lack of clarity, lack of clarity is the biggest cause of bugs. Thus there would be more bugs not fewer. In fact, this kind of thinking leads to the increased use of loose equality throughout as controversially espoused by Kyle Simpson.== undefined
as an option.Also note that the
undefined
literal can be redefined, everywhere but the global scope.== null
is the only safe usage of==
.As stated many times @ljharb, there is communication from Bredan Eich himself that TC39 rejected null in ES6. I hope you will take the advice of those who actually wrote the language and were there when these decision were made.
Clearly null cannot be deprecated because too many programs now rely on this buggy bit of code, but that has been discussed and an expressed desire at the highest levels of Javascript architects.
Incidentally, even the MDN reference makes use of the
undefined
literal in numerous examples, it is well accepted and good practice, but again you make extreme statements without supporting proof.I would still like to know, how does using
== null
to test for an unintentional absence of a non-object make any sense? If== undefined
is deprecated please provide proof. Or is there no proof?Thanks for the discussion, everyone. There isn’t enough support on the team to implement this change, so we are closing this issue. As a reminder, you do have several options for getting this functionality including the use of the
no-restricted-syntax
rule or creating your own (either with or without eslint-rule-composer.There are only two logical approaches here.
allow null
rule and neither== null
nor== undefined
should be permitted.undefined
, a separate linting rule warning against redefinition of undefined should be included. Only== undefined
has the correct ECMA262 meaning to included both a test objects and non-objects when testing for emptiness, to include== null
as the only exception is incorrect in terms of ECMA262 spec, it implies a test of absence of objects and will make code unclear.Indeed, given the serious warning from MDN, and the serious problems that would be caused by redefining
undefined
, that should be a rule in EsLint regardless! If a developer redefinedundefined
, would that make any difference to== undefined
being a less robust code? Of course not, the two are separate issues! If a developer redefinedundefined
they have more to worry about that a linting option, their code would be impossible to debug regardless of EsLint!@ljharb When the creator of Javascript, Brendan Eich, writes that there is reason to believe typeof null is a bug, it is not a misrepresentation to state that there is wide support for concern over the use of null. Null was specifically excluded from ES6 defaults by the TC39 committee despite robust attempts to have it included - this is fact.
Regardless, I think we are digressing from the point.
As @SyMind correctly stated, ECMA262 states that
null
is only to be used as the absence of an object -undefined
is the absence of any value (including an object). Thus,null
in ECMA262 script is a specific instance ofundefined
, a specific instance that is widely accepted to be buggy. That APIs returnnull
is not a “recommendation” to usenull
, it is merely ECMA262 specification that it far too this late to change. The argument that it is a recommendation is akin to stating that gas stations selling fuel is a recommendation that we should use gas rather than electric cars - it’s a straw man argument. Only humans can make recommendations, not browser APIs. The only internal JS method that returns null is string.match(), again, we can’t change that, but JS programmers can follow advice from highly experienced programmers to never usenull
.Only
== undefined
has the correct ECMA262 script meaning to included both objects and non-objects when testing for emptiness.The facts are as follows:
Javascript - The Definitive Guide
, advised programmers to setStrings
,Numbers
andBooleans
tonull
instead ofundefined
if an empty value was required. This is corrected in the 2021 edition to be released.allow null
included as a linting option? To make it easier to test for bothundefined
andnull
because as you correctly state, null and undefined are both returned -null
only in the case of Objects.undefined
to be excluded from the the linting option== undefined
? Of course not. This would result in Object properties being set as one thingundefined
yet tested for by the a less common value== null
, a value that has a specific meaning to objects only, thus causing complete lack of clarity. Only== undefined
has the correct ECMA262 script meaning to included both objects and non-objects when testing for emptiness.undefined
.== null
without== undefined
cause more or less confusion and clarity - the most serious threat to robust code - of course it does, especially given points 1 and 3 above.undefined
, is it logical to cause more lack of clarity by making an illogical rule to exclude== undefined
thus still allowing users to redefineundefined
, or would it be more logical to add a linting rule to warn about the redefinition ofundefined
as well as a== undefined
option.== undefined
, further, null is only returned by a handful of methods, and many API calls.typeof === 'object'
bug. Thus avoidance, if possible, should be an entirely recommended goal. Notwithstanding, this may not be the aim of aallow == undefined
rule. Simply the rule should be included because of point 1 alone or point 3 alone!If you do anything on the web, you deal with many APIs, some of which return
undefined
and some which returnnull
, including in JS itself (''.match(/./)
, eg). It’s impossible to only ever use one of them - and in the world of modern web dev, most of your code is from dependencies, which you can’t/shouldn’t lint at all, and any of these might return whichever nullish value you hate the most. The purpose of this rule is to prevent all usages of==
/!=
, and the choice to make an exception for== null
was, i assume, because that was both the common idiom, and also more robust than== undefined
.@lemonbob there’s a few inaccuracies in your comment; TC39 never “selected” a preferred base value for JS,
undefined
has always been the preferred base value since the language’s inception.null
is in no way deprecated by TC39 (which I am a member of). What programmers “should do” isn’t the point; because they can redefine it, robust code needs to be concerned with it. As for coercion, if you’re arguing what programmers should do, then one thing they shouldn’t do is implicitly coerce anything 😃== undefined
should absolutely not be permitted by this rule, and imo a clean codebase would only ever use== null
(or!= null
), or===
.It seems like there’s a misunderstanding about what this rule is intended to enforce.
eqeqeq
is not recommending usingnull
orundefined
in general. Theallow-null
option exists so that folks can use the idiomatic shorthanda == null
instead of having to write outa === null || a === undefined
. The rule doesn’t enforce setting anynull
values - it’s just for this check.I can see why folks want to try coalesce around a single nullish value, but this feels like a misapplication of this recommendation. Just because the code doesn’t have the keyword
null
in it doesn’t mean it isn’t checking if the value isnull
or not. Sincea == null
is the convention, is safer, and one can always usea === null || a === undefined
if they really don’t want to usea == null
, I don’t think adding another option makes much sense. We should be encouraging the safer option.The good news here is that ESLint is pluggable! If this conversation doesn’t lead to implementing the requested feature in core, we encourage you to create your own custom rule (eslint-rule-composer could be really useful here).
Makes sense to me, but I guess this would be
["error", "always", { "undefined": "ignore" }]
, rather thanallow-undefined
.allow-null
is deprecated in favor of"null": "always" | "never" | "ignore"
.This is documented at the end of the always section, and in the allow-null section. It feels that the document is missing examples or a whole new section for the
"null"
option.The new option for
undefined
, if accepted, should probably match the existing one fornull
(though, I’m a bit confused about"never"
).