Nullish unary operator `?`

Yeah, sorry, I've confused ... I thought I saw somewhere such syntax (
The closest syntax that exists it is:

if (a ?? false) {
  ...
}

That's not quite the same. As that will also be false for values like 0 and "".

Why did you propose it as "not nullish operator"?
The nullish operator should be enough as it is like

instead of writing

if(param1 === undefined || param1 === null)
  return;

Just
?param1

And not nullish can be used as
??param1

And so on..

You might have already read this in this discussion, but the ? operator does not behave in the same fashion as the logical not ! operator:

let a

!a // true
!!a // false
!!!a // true

?a // false (because a is undefined)
? ?a // true (because it's the same as: ?false)
? ? ?a // true (because it's the same as: ?true)
? ? ? ?a // true (because it's the same as: ?true)

so we can't really create a "not nullish" in the way you proposed.

Also, I definitely think that the ? operator should be checking if the variable is not nullish, instead of checking if it is nullish. When reading the expression if (?a), the question mark will make it so we read : if "a" exist. This is the same idea for the nullish coalescing operator, where a ?? b is read as: "a" if it exists, or else "b".

On the other hand, I do agree that the name "not nullish operator" is not that great, because it already contains a negation in it. When negating it like !?a, we would read it as : if "a" is not not nullish, which is really a pain to process mentally. The name "existential operator", like in CoffeeScript, would be way more easier to understand, as ? would simply mean "exists", and !? "does not exist".

What do you think about this ?

I think might have missed that, sorry.

TypeScript has Non-null assertion operator which is known as non-null operator. So the !. operator in TS, means the following property is exists.

I'm roughly think like, if we comprehend ?param1.prop1 as prop1 is not nullish and param1!.prop1 as prop1 is not nullish, will make confusion because they basically will have the same purpose to indicate the same thing.

Since ! operator used to determine if its operand is a falsey value, it can be combined with ? operator I think :thinking:.

So my suggestion can be like:

let a;

?a // true aka. a === null || a === undefined
!?a //false aka. a !== null && a !== undefined
!!?a //true aka. !(a !== null && a !== undefined)

?!a; // syntax error because !a usage will always return boolean
??a // syntax error because nullish operator will return boolean and 
    // no need to use nullish operator on boolean type

The TypeScript Non-null assertion !. operator would be closer to the Javascript Optionnal Chainning ?. operator, while the proposed Not-nullish ? operator is closer to the CoffeScript Existential .? operator.

So in your case, ?param1.prop1 and param1!.prop1 does not have the same meaning at all, in the first you are asserting that param1.prop1 is not nullish, whereas in the second you are asserting that param1 is not nullish.

Note that you could assert that both are not nullish by doing: ?param1?.prop1

I'm not sure throwing a syntax error on ?! and ?? because their value is expected would be a good idea, because it would create complicated edge cases for an operator that aims to be dead simple. In my opinion, this would more be a job for linters, rather than engines.

On the other hand, a syntax error on ?? should be thrown (and will be thrown anyway by the engines), as it is forming a nullish coallescing operator. I've already mentioned this behavior in the github proposal, if you haven't already had a look!

1 Like

Agreed, while ?!a may be useless (in either interpretation of this), I don't think I would want it to be a syntax error. There are lots of ways to do useless things, and there's no way to consistently flag them as syntax errors. ?(!a) would also be useless, as would ?(2+2), and !!!!a. The only reason why we might flag it as a syntax-error is if we wanted to reserve the combination of those two characters together (?!) as a potential future operator.

1 Like

I was referring to having both non-nullish operator and non-null assertion operators at the same time and the stage of learning and understanding their purposes. Because in your suggestion, they will kind of have the same indication but not the same meaning in a use case scenario.
Let's say, someone learning the meaning of the these two operators. Differencing them from each other may create confusion because while ? is used to determine the variable is not-nullish and !. to determine non-nullish can lead to have this question:

This doesn't make any sense. Why ! and !. operators are not designed to indicate the same thing? Instead they use the ? operator.

? operator can be seen like a question mark sign in Spanish language to indicate that you need to expect a question from the following sentence/expression, rather than confirmation.
Like:

¿Qué pasa?

If ? is used to determine a variable is a nullish one while !. is used to indicate that the operand is non-nullish, that will lead to a correct understanding.


I also saw your mention ?? on your proposal, but I was mentioning it with another logical aspect rather than referencing to the nullish coalescing operator. To my knowledge, the nullish coalescing operator is only used between two expressions and using it before an expression will not the same thing, and it will lead to have confusion in our hands and that's it.

So if I understand you correctly, you want ? to mean "is nullish?", because that would then make the "!" in "!." have a not-ness to its meaning, as it's not "?". I can see that.

I'm still not convinced, but I can't come up with a good reason why :P - maybe I just like "?" meaning "is defined?" because that's what it means in other places like coffeescript, so that's what I'm used to.

I think the question would more likely be: why the Typescript !. operator is used instead of the ?. operator ?

Writing object!.property and object?.property is not the same.

The Typescript !. operator has nothing to do with ?, or ?., it is a compilation operator, not a runtime one, and checks for types. Once your typescript code is transpilled to javascript, it does not exist anymore, and if in some way your object is null or undefined, your program will crash.
On the Optional Chaining ?. side, the check is done in runtime, and it checks whether the variable value equals null or undefined.

With that in mind, the proposed ? operator is way closer to the ?. operator than it is to the !. one.

Also, the ? operator and the ?. (or !.) are not used in the same place:

  • The ?. operator is used between an object and its property, in order to ensure the object is not nullish, and therefore it does not throw if it's the case
  • The ? operator is used for any kinds of value, and is testing if this value is not nullish

The place is different, but the behavior is the same, that's why having ?. checking whether the value is nullish would not be coherent with the ?. one (or other operators of the language, like ??).

I hope this will help you to better understand why I persist to think that the ? operator should check for "not nullish".

1 Like

I would love this, i could for example easily test if an object i got from document.getElementById() really exists

1 Like

What about:

if (a ?? true) {
  // ...
}

This also pretty short

Hi @SiddharthShyniben, thanks for participating in this discussion!

What we want here is to check whether a variable exist or not (i.e. is undefined / null or not)
The problem with your code is that it would return both true or false for the case of not nullish variables:

0 ?? true // 0 -> false
1 ?? true // 1 -> true

which is understandable, because ?? would evaluate the second operand only if the first one is nullish, so falsy values will still be evaluated to false (which we don't want here).

Also, this method does not always return a boolean, as it can directly return the value of the first operand. This would be less clean for type assertion, and might also confuse programmers.

2 Likes

Thanks for the explanation @Clemedz I get it now.

1 Like

A variable exists even if it’s undefined or null - nullish coalescing is about the value, not the variable or property you’re using it with.

Indeed, "to check whether a variable exist" might sound a little confusing compared to whether a variable is declared or not.

A better way to say that, still using the "exist" term (taken from CoffeeScript "existential" operator), would have been: "to check whether a value exist".

Both null and undefined exist; they’re values. A variable can be undeclared (in sloppy mode, it pretends to have a value of undefined), or declared and undefined, or declared and defined as undefined, etc.

The term “exist” is just categorically inappropriate here, no matter what coffeescript has named something.

Coffeescript's existential operator will actually check if the variable does not exist (is not defined) as well as checking if it's null or undefined, which is perhaps why they adopted that name.

Probably the best word we can use when a value is null or undefined is "is this value nullish?", as that seems to be the word we're converging upon with the names of different operators.

Oh I see, I wasn't aware that Coffeescript existential operator was also checking whether the variable was declared or not! In that case, the word "exist" makes much more sense in Coffeescript than for the proposed ? operator.

Indeed, using the word "nullish" would be quite consistent with other operators, however the ? operator is checking: "is this variable not nullish", and the problem (I have) with this way to put it is that it already contains a negation.
When checking for the opposite (using !?), we would be checking: "is this variable not not nullish", and even if it simply means: "is this variable nullish", this would still be the way it'd come to our mind, and it would be a pain to reason about.

Actually, reading back what I wrote in my first post proposing this operator, I see I already came with a nice way of expressing this idea, using the word "defined".
So I guess a right way of describing the operator would be that it checks: "is the variable defined".

And extending the idea, maybe the ? operator could be called the defined operator (although "defined" sounds less expressive (at least for me) than "not nullish"). What do you think about that?