Closed Primajin closed 1 year ago
You can write: (condition1 != null) && condition2
, or, depending how you want to use the result: (condtion1 != null) && (condition2 != null)
In any case, duplicate of #4.
Well but I would need to write condition1 not equal null and not equal undefined and condition2 not equal null and undefined... which is cumbersome
Well but I would need to write condition1 not equal null and not equal undefined
Which is exactly what != null
means.
Sorry my bad you are absolutely right, I am so used to !== that I didn't spot that. Thanks!
Well but I would need to write condition1 not equal null and not equal undefined
Which is exactly what
!= null
means.
The issue is that != null
will also consider objects with the [[IsHTMLDDA]]
internal slot to be undefined
, which ??
, ?.
, !== null
and !== undefined
won’t.
Hi @ExE-Boss that is very interesting, this is the first time I hear that x != null
is not strictly equivalent to x !== null && x !== undefined
, can you please provide a link or an explanation where I can know more about this / see an example?
Annex B § The [[IsHTMLDDA]]
Internal Slot, https://github.com/tc39/ecma262/issues/668 and https://github.com/tc39/ecma262/pull/673 explain why this legacy behaviour is needed (TL;DR: legacy IE checks).
// This is actual code that exists on old webistes:
if (document.all) {
// Internet Explorer code
} else {
// NetScape Navigator code
}
@ExE-Boss Hmm... Do you know why this behavior does not appear directly in the Abstract Equality Comparison spec though?
It’s in annex b, which is legacy requirements for web browsers, which currently is not inline.
Nice! Thanks everyone, sorry if I drifted the topic off a little bit.
Babel could use an operator like this: https://github.com/babel/babel/pull/11248#discussion_r391759571
I'm glad to see this isn't closed. In addition to the above concerns about edge cases in the exact meaning of foo != null
, I wanted to raise the point that some linters or coding standards require the use of strict equality checks (===
/ !==
) and treat loose equality operators as an error. That means spelling out foo !== null && foo !== undefined && bar(foo)
, which would look a whole lot cleaner as foo ^^ bar(foo)
, or whatever double-special-character pair would be safe to use there.
@thw0rted
I'm glad to see this isn't closed.
Note that this proposal is at stage 4, which means that there will be no further changes beyond bugfixes. Any new feature will be part of another proposal.
(To the maintainers of this repo: Is it time to do some housekeeping and close most open issues?)
I wanted to raise the point that some linters or coding standards require the use of strict equality checks
We can either adapt coding standards and linter rules so that they allow us to use an existing feature of the language, or duplicate an existing feature of the language so that we can circumvent coding standards and linter rules. Personally, I tend to prefer the first option.
That means spelling out
foo !== null && foo !== undefined && bar(foo)
, which would look a whole lot cleaner asfoo ^^ bar(foo)
, or whatever double-special-character pair would be safe to use there.
I’m not sure that == null
is substantially more confusing than your proposed ^^
(the first time I would see ^^
in an unknown language, I would wonder if it is the logical xor operator). But in any case, if you (or your coding standard) fear that a casual reader will misunderstand == null
, there is still room to take advantage of existing features of the language, instead of creating yet another notation to be learned. I’m thinking of: is_nullish(foo) && bar(foo)
no further changes beyond bugfixes
Welp, that's that, I guess. Makes sense, and certainly this isn't nearly as important as the ??
version. Maybe next time.
adapt coding standards and linter rules so that they allow us to use an existing feature of the language
The coding standards and linter rules are there because loose equality is a footgun, and the language feature is used wrong by accident more often than it is used right on purpose. (Reasonable people can disagree about whether this is in fact true.) We could update the standards/rules to say "except when it's loose-equals null because you meant 'null or undefined', as long as you did it intentionally and know what you're doing", or we could add an operator that succinctly and explicitly means "I am checking for null or undefined".
the first time I would see ^^ in an unknown language, I would wonder if it is the logical xor operator
Me too; I picked the first special character I could think of that I was pretty sure didn't have an existing meaning -- naming things is of course one of the Hard Problems. In #4, ?!
was proposed, which fits in with ??
much more naturally but I believe would conflict with a combination of the ternary and not operators, e.g. foo ? !bar : !baz
. I'm confident that smarter folks than I could come up with a valid symbol combination that makes sense. (Later in that thread, someone suggested ?&
and I can't think of a valid preexisting construct with those two together, so let's go with that for now.)
there is still room to take advantage of existing features of the language
It would be trivial to write a function, but you could say the same thing about ??
, which made the cut. Why should ??
get in but not ?&
?
I’m not sure that
== null
is substantially more confusing than your proposed^^
I agree. In codebases I work on we use linter rules to enforce tripe equal for anything but null/undefined comparison. Using == null
is only allowed when the value can be both null
or undefined
. This way we have == null
only in the correct places and === undefined
/=== null
in other places.
We also have type guards such as isNotNullOrUndefined
to use in functions such as array.filter
.
In my eyes, adding a special operator for a case which already has a perfectly valid and concise solution is superfluous and confusing.
In my eyes, adding a special operator for a case which already has a perfectly valid and concise solution is superfluous and confusing.
So, you were also against the nullish operator that did get in, ??
?
No I wasn't since ??
makes the following readable:
// Before with ternary
console.log(data.nickname != null ? data.nickname : (data.name != null ? data.name : 'N/A'));
// Before with functions
console.log(getDefault(getDefault(data.nickName, data.name), 'N/A'));
// Now
console.log(data.nickname ?? data.name ?? 'N/A')
function getDefault() {
for (let a of arguments) {
if (a !== null && a !== undefined) { return a; }
}
}
getDefault(data.nickName, data.name, "N/A");
That is, IMHO, exactly as "readable" as data.nickname ?? data.name ?? 'N/A'
. But the point of having a native operator is that you don't make everybody roll their own getDefault
. MDN is rife with polyfills for all kinds of syntactic sugar added in the last few rounds of ES -- think about all the helper methods for interacting with Arrays, Object.entries
, etc.
All I'm saying is, if we're going to add sugar, let's at least be consistent. My point above was that ?&
would provide similar value to ??
in similar sorts of situations, so if we're going to have one, it makes sense to add the other. I don't see anyone here disagreeing.
Oops: both of our getDefault
examples are wrong because they don't exhibit short-circuiting behavior. In the case of data.name ?? lookupDefaultName()
, the function call won't run if data.name
is non-nullish, but getDefault(data.name, lookupDefaultName())
always runs the lookup function even if it's not used.
That leaves us with the ternary operator for comparison. I believe it's about as verbose in the "AND" case as with the "OR" case:
x = data.nickname != null ? f(data.nickname) : (data.name != null ? f(data.name) : 'N/A'));
x = (data.nickname ?& f(data.nickname)) || (data.name ?& f(data.name)) || 'N/A';
To me, the latter (hypothetical) version conveys intent better and avoids the complexity of nested ternary operators.
It would be trivial to write a function, but you could say the same thing about
??
, which made the cut. Why should??
get in but not?&
?
My requirements for a replacement of ??
and ?&
using existing language features, are:
Applying DRY, I short-circuit what I was going to write and backlink to https://github.com/tc39/proposal-nullish-coalescing/issues/4#issuecomment-321968495.
Do you have a list of languages that have "nullish AND"? If so, what are the operators used?
I don't know of a similar feature in other languages, but then the first I heard of ??
was actually in Typescript release notes, so I'm the wrong guy to ask. (I got out of C# before it had ??
, close to 15 years ago.)
I agree that at this point it's looking more and more like a shorthand for != null &&
which is not a great argument in favor of a new feature. If it came along anyway, I'd probably use it, but if anything this is probably going to make me take a harder look at my linter config.
I second https://github.com/tc39/proposal-nullish-coalescing/issues/61#issuecomment-648899863 - since if we add the sugar for != null ||
why not also for != null &&
.
We also lint everything to triple equals so that could be configured in the short term but having a shorthand in the long term would definitely be nice.
??
is not syntactic sugar for != null ||
though, it is different.
Anyway, in my opinion, != null
is perfectly readable and I do not see a need for an operator which does exactly the same as != null
. I believe it would add more confusion than benefit.
It seems that in many of the examples for this operator, the value ends up being repeated in RHS
name = data.name != null ? capitalize(data.name) : 'N/A'
name = (data.name ?& capitalize(data.name)) ?? 'N/A'
which makes me wonder if this use case was actually better served by the suggested optional chaining support in the pipeline operator proposal (pipeline proposal, optional chaining suggestion).
name = (data.name ?> capitalize) ?? 'N/A'
Do you have a list of languages that have "nullish AND"? If so, what are the operators used?
I guess many of the popular other languages out there are typed by default - so that the need for such an "nullish AND" didn't really arose.
When dealing with data where 0
is a valid value one can easily make the mistake in ES to form a check for the value not considering that ES interprets 0
as false. That's why ??
became so handy but it doesn't feel complete without and AND
version (since it's OR
)
Is it too late to propose an alternative syntax? Since type checking is used when using three equal signs, then three OR or/and AND could be used.
null ||| true
//returns true
0 ||| true
//returns 0
null &&& true
//returns false
0 &&& true
//returns true
null ?? true : false
//returns false
0 ?? true : false
//returns true
Is it too late to propose an alternative syntax?
Yes it is. Nullish coalescing is stage 4 and already implemented by browser vendors.
See https://tc39.es/process-document/ for details about proposal stages.
Too bad.
Thanks for the timely reply @MatthiasKunnen
Not sure if you mean the same thing. The syntax for nullish coalescing is indeed fix - but for nullish AND as per this thread it's still completely open and up for discussion wether this should be a thing at all
Closing, since this proposal is at stage 4.
The nullish coalescing acts like a logical OR where it returns the left part when it's not null or undefined.
Is there also an easy way for an AND where it returns the right?
Typically by chaining AND conditions one expects "the program to run from left to right and stop + return" if a condition is not met. Normally falsey values, with nullish coalescing only NIL (null + undefined)
I would like to achieve an AND chain like so:
But it should not stop on falsey but only on null/undefined.
Is there an easy way?
Doesn't feel right.