Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Nice explanation!

Although I’m surprised there is no mention of the best solution for iterating both keys and values:

for (const [key, val] of Object.entries(obj)) { console.log(key, val) }

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...



Note that Object.entries also returns keys as strings (and not keyof T), just like Object.keys does. It has the exact same problem and rationale as explained in this article. This means that if you just want to loop, you’re good, but the moment you need something fancier than a console.log you might need the keys to be typed stronger again.


In many cases though, you only need a correctly-typed key in order to index into the object to get the value -- if you've already got the value, you're fine. And if you need to limit yourself to keys that are defined on the type you're using (rather than arbitrary keys which might exist on the object at runtime) then you need to check anyway.


Object.entries has the same problem: https://stackoverflow.com/q/60141960


It has some of the same problems. It doesn't have the problem of being unable to read obj[key] because typescript doesn't realize it's the same object.


It has that same problem actually:

https://news.ycombinator.com/item?id=36458300

And according to the article, the issue isn't that TS doesn't realize it's the same object, it's that the object might have more keys than what is declared in your interface.

Perhaps what you meant to say is that you can directly use `val` instead of `obj[key]`.


> And according to the article, the issue isn't that TS doesn't realize it's the same object, it's that the object might have more keys than what is declared in your interface.

The main issue at hand was inability to use `options[key]`.

"the object might have more keys" was a possible issue, and was the reason typescript was blocking access to `options[key]`, but it wasn't the main problem.

> It has that same problem actually:

> Perhaps what you meant to say is that you can directly use `val` instead of `obj[key]`.

How is that different from what I said?

Because you can directly use `val`, and because that's better than `obj[key]` anyway, you "don't have the problem of being unable to read obj[key]".


`Object.entries` and `Object.values` are unsound[0] because they aren't typed as defensively as `Object.keys`. And that seems unlikely to change[1].

[0]: https://tsplay.dev/N7zKRw

[1]: https://github.com/microsoft/TypeScript/issues/38520


Great, neat way!


I tend to try to avoid for loops unless absolutely necessary. I prefer to express operations as various combinations of map, reduce, filter, etc.


I tend to avoid map and filter unless the code I'm writing can be naturally expressed using them. I almost never use reduce. Sum of a list is one of the few reasonable use cases. I've seen some horrific reduce code that's working very hard to avoid an explicit loop.

If I need to count occurrences of each character in a string, I'm using a loop.


Is there a functional rationale for this or more of style thing? I almost never use reduce but I use map and filter (and forEach) everywhere. The syntax of for loops just seems so dirty to me but maybe I just stylistically like the functional / immutable approach to architecting code which is why I use Ramda.


input.split('').filter((c) => c === chr).length;

Edit: ah I assume you mean more like a histogram. Yeah, that's going to be less clean, e.g.

input.split('').reduce((acc, el) => ({...acc, [el]: ( acc[el] ?? 0 ) + 1 }), {});


This is exactly the type of code I'm talking about. That spread operator is producing a lot of garbage (in the GC sense) for no real reason. It's just to avoid mutation and a loop.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: