Live data from Hacker News

Abuse of the nullish coalescing operator in JS/TS

fredrikmalmo.com

61–70 of 70 posts

Re: Abuse of the nullish coalescing operator in JS/TS

#62
post #57
post #47

Earlier quoted context omitted.

Assuming assert existed, it would almost certainly be judging its value for being falsy , while the ?? operator judges its LHS for being nullish , which is a narrower category. For strings, this affects whether the empty string is acceptable or not.

> Assuming assert existed It's a function you could write for yourself and give it whatever semantics you feel is best. No changes to the language required for this one.

[deleted]

Re: Abuse of the nullish coalescing operator in JS/TS

#63
I cannot tell if the author would agree with this, but here’s my take:

There’s nothing wrong with using the ?? operator, even liberally. But in cases where 1) you don’t think the left side should be undefinable at all or 2) the right side is also an invalid value, you’re better off with an if-statement and handling the invalid case explicitly.

But I’ve used ?? thousands of times in my code in ways unrelated to 1) and 2).

Trivial example:

const numElements = arr?.length ?? 0

IMO this is fine if it’s not an important distinction between an array not existing and the array being empty, and gives you an easier to work with number type.

Re: Abuse of the nullish coalescing operator in JS/TS

#64
post #44

Earlier quoted context omitted.

while this is nice, the type itself doesn't encode the logic (unlike refinement type) i think this would be really nice if validation libraries like zod returned branded types when they are validating non-comp-time types (like z.ipv4() should return some IPv4 branded type)

The type encodes the logic in the schema, it is absolutely a refinement as every parser is. Maybe you meant a comparison with dependent types? Now every time you will have to use a NonEmptyString255 as a type it has to be branded by passing through the constructor, so you can't pass a normal string to an API expecting it, and you get the error at type level. The logic is encoded in the schema itself, which you can cl…

oh i guess you use zod in every single part of your application? not just api level.

i was suggesting the result of zod parse is a type that shows how it’s been refined

however, .ipv4().parse(“..”) returns a type “string”

Re: Abuse of the nullish coalescing operator in JS/TS

#65
post #26

Early errors are good, but I think the author overstates the importance of filtering out empty strings --- I disagree that erroring out when the app doesn't have ALL the data is the best course of action. I imagine it depends a bit on the domain, but for most apps I've worked on it's better to show someone partial or empty data than an error. Often the decision of what to do when the data is missing is best left up t…

Sure, but in that case string | undefined is the correct type, and turning it into string | “” isn’t helping anybody. It’s the difference between: if (fooBarDisplayName) { show div } And: if (foobarDisplayName && foobarDisplayName.length > 0) { show div } Ultimately, type systems aren’t telling you what types you have to use where - they’re giving you tools to define and constrain what types are ok.

I'm not sure I follow the point you're making

My example is we want to skip the div if empty or undefined. We can't throw on assignment so we leave it as as string|undefined.

When we go to display, we have to check if the string is empty anyway, right? What if it's empty in the DB or API response?

No matter what the display-component is doing something to prevent showing the empty string.

` if(fooBarDisplayName.length) { show div } `

or

` if(fooBarDisplayName?.length) { show div } `

I'm not sure what we gain by leaving it as `string|undefined`

---

If there was a "NonEmptyString" type maybe I could see where you're coming from.

I guess you could argue treating `string` like a `NonEmptyString` type seems error prone. The compiler can't verify you've done the check. At some point someone will set a string when it's empty or not do the necessary check.

You'd want a separate non-string type to make sure it's actually been parsed

Re: Abuse of the nullish coalescing operator in JS/TS

#66
post #64

Earlier quoted context omitted.

The type encodes the logic in the schema, it is absolutely a refinement as every parser is. Maybe you meant a comparison with dependent types? Now every time you will have to use a NonEmptyString255 as a type it has to be branded by passing through the constructor, so you can't pass a normal string to an API expecting it, and you get the error at type level. The logic is encoded in the schema itself, which you can cl…

oh i guess you use zod in every single part of your application? not just api level. i was suggesting the result of zod parse is a type that shows how it’s been refined however, .ipv4().parse(“..”) returns a type “string”

there’s problem with branded types this way now that i think of it

string

type nonEmptyStr = string & NonEmpty

type ipv4Str = string & IPv4

it’s not obvious how you’d automatically determine ipv4Str is also a nonEmptyStr, since the types themselves are just labels, they don’t store the refinements at type level

Re: Abuse of the nullish coalescing operator in JS/TS

#67

It seems Rust's unwrap is the exact opposite of ?? "". It throws an error instead of using a fallback value, which is exactly what the author suggests instead of using ?? "".

Author here. I believe I did a poor job of explaining what I meant by this sentence in the article. Sorry about that.

As you, and many others, have pointed out, `?? ""` does not do what `.unwrap` does. `unwrap_or_default` would have been a better comparison for what it actually does. What I tried, and failed, to communicate, was that both can be used to "ignore" the unwanted state, `None` or `undefined`.

I guess the rust equivalent to what I would like to see is `nullable_var?`, and not unwrap as that will panic. That would be equivalent to the `?? throw new Error` feature mentioned further up in the comments.

Re: Abuse of the nullish coalescing operator in JS/TS

#68
post #63

I cannot tell if the author would agree with this, but here’s my take: There’s nothing wrong with using the ?? operator, even liberally. But in cases where 1) you don’t think the left side should be undefinable at all or 2) the right side is also an invalid value, you’re better off with an if-statement and handling the invalid case explicitly. But I’ve used ?? thousands of times in my code in ways unrelated to 1) and…

I definitely do agree with this! It's a very helpful operator in a lot of cases. I think the two cases you point out are prime examples of cases where I would prefer _not_ to encounter them.

Re: Abuse of the nullish coalescing operator in JS/TS

#69

> I've come to see this ubiquitous string of symbols, ?? "", as the JS equivalent to .unwrap() in Rust Isn't this more like `unwrap_or`?

Author here. It is. I did a poor job explaining what I meant by this. I tried to elaborate https://news.ycombinator.com/item?id=46089466. I'll also update the article to reflect this:) Thanks for pointing it out:)

Re: Abuse of the nullish coalescing operator in JS/TS

#70

> Personally, I've come to see this ubiquitous string of symbols, ?? "", as the JS equivalent to .unwrap() in Rust It's funny you bring this up because people opposed to `.unwrap()` usually mention methods like `.unwrap_or` as a "better" alternative, and that's exactly the equivalent of `??` in Rust.

Semantically the two are kind of opposite; the similarity is that they're the lowest-syntax way in their respective languages to ignore the possibility of a missing value, and so get overused in situations where that possibility should not be ignored, leading to bugs.

This is exactly what I was trying to communicate in the article. You've put it in a way clearer way here though. Thank you:)
Post reply on HN