Hacker News new | ask | show | jobs
by eyelidlessness 1190 days ago
> You are doing part one. Is part two occurring?

Valid feedback. I even thought of adding it myself, because implied stuff isn’t obvious. I felt it worth communicating because there’s value in what’s implied that isn’t available in the type system. To the extent I have team members consuming the same code, I would definitely communicate the intent. To the extent I have reviewers who read the code, I do discuss it.

To the extent this is in a type parameter position, the onus is on the person writing the function signature and… well if they don’t want a footgun, they have every opportunity to not gun their foot. But that’s entirely opt in by the time they’ve reached that point.

1 comments

I think at this point we'll agree to disagree.

I will offer this as a middle ground that I'm not even 100% sure will work since I'm not in front of a TypeScript interpreter.

What about just defining it as object? Would work for object.Keys, but not sure how the function consumers would get along with it.

Completely aside from these details, thank you for stepping back and discussing this in good faith. It made a discussion that was going badly feel at least like communication. I appreciate that, and I’m glad to land at a place where we’re not necessarily on the same page but we’re at least recognizing we have similar priorities. Cheers!
> What about just defining it as object?

That’s pretty much the intent of the constraint. I don’t have time to sit with a type checker right now, but I don’t think we disagree as much as you might think. I arrived at this from years of trying to find the best way to express types which are as strict as possible with as much clarity as possible.

Unfortunately the object type is basically any non-null value, as is {}. They both intuitively mean what I want. They also inherently allow PropertyKey keys, which is effectively Record<string | number | symbol, any>, which is looser than the “dictionary” type I often want to accept in these scenarios.

A better question (for me, and maybe you and maybe all of us who want type certainties) is why we even accept dictionaries in object shapes when Map is the obvious expression of that type. I’ve repeatedly wanted that and shied away from it because it requires too much change for very little gain.

I think with Map the answer is somewhere between momentum ("we've always used objects as dictionaries") and some misapprehensions easily shifted with basic caniuse statistics. Map still feels "too new" to some developers, despite being ES2015 (8 years old now!) and available in every browser that supports the arrow operator for functions has Map (and Set) out of the box (no need for polyfills in 2023, ever).

Probably the only other reason I've seen is "JSON interop" is "hard" because Map doesn't natively serialize. I think `new Map(Object.entries(oldDictionaryObject))` and `Object.fromEntries(someMap.entries())` are sufficient for most serializer boundary cases (even without feeling fancy and doing that as a true JSON revivifier/resolver pair).