4 ms·
I make an exception for using any in type params which extend type params, eg const foo = <T extends Record<string, any>>(dict: T) => … This is a good signa
by eyelidlessness 4y ago
I make an exception for using any in type params which extend type params, eg
const foo = <T extends Record<string, any>>(dict: T) => …
This is a good signal that foo maps over dict in some generic way that cares more about its dictionary-ness than its values. Sure, unknown works in that position too, but at least IMO the “doesn’t care” bit is more informative than “doesn’t know”. The latter might imply more type narrowing will happen than is the case.
- alexgrover 4y agoThe problem with that is that when consuming of the dictionary, “doesn’t know” is actually more appropriate. If you then access Object.values(foo) in your method you are given an iterable of anys which is unsafe.
- eyelidlessness 4y agoIf the function is doing something with the values which is unsafe, sure. My point was the more relaxed constrain on the type signature can be used to imply it’s only concerned with the dictionary’s keys.
- alexgrover 4y agoComing back to this after the other thread cooled down a bit lol - to me, unknown actually implies that the function doesn’t care about the values more than any, as the compiler will enforce that they’re unused. And in any case, I’d almost always lean towards the option with stronger type safety guarantees. Especially in a team environment when someone else may be modifying your code later. As a convention, I almost never use any.
- eyelidlessness 4y agoTo me `unknown` signals an intent to know, as in “I don’t know yet” (or put another way, “I don’t have any prerequisites for accepting this value, I can and will narrow it as appropriate”). In a codebase that otherwise takes type safety seriously, `any` in a type parameter (again to me) means “I don’t have any type narrowing agenda for this thing, it’s along for the ride and coming out the other side the same way it showed up”.
- TheCleric 4y agoThen use unknown. Either you know what's in the dictionary and can type it or you don't. Stop being lazy.
- eyelidlessness 4y agoI’m not being lazy? I am taking extra time and expending extra energy to make sure the metadata I put in code is as informative as possible. In this use case `any` carries more information. I use `unknown` in place of `any` exactly as it’s intended wherever I’m able. Also, please don’t continue to be a jerk at me.
- TheCleric 4y agoOkay I'll stop being a jerk and engage in good faith. I'll assume you think this is a valid use case for any and it communicates something important. My counterpoint is this: communication involves two things, someone stating a message and someone receiving a message. You are doing part one. Is part two occurring? It may be because of certain conventions in your codebase or team, but I've personally never seen any used in that manner ever, so I would not receive your intended message. If I were in the same situation I would use unknown and add a comment stating that the type is of no importance since I'm only worried about the keys. That way my message is clear and I prevent future developers from having to debug code where they assume the value is of a certain type and start accessing parameters and methods that do not exist.
- TheCleric 4y agoAs an addendum if the function only needs the keys I would possibly just have the parameter be a string[] that expected the user to call object.Keys to pass to. That way the function isn't asking for parameters it doesn't really care about. Though I do get the appeal of having the function call object.Keys if it's called frequently so as not to have to sprinkle that call everywhere.
- eyelidlessness 4y ago
- TheCleric 4y agoAny doesn't mean "doesn't care". Any means "YOLO, do whatever you want, I'm one of those cool parents who'll let you smoke and drink beer."
- eyelidlessness 4y agoWhat is the distinction?
- TheCleric 4y agoThe distinction is just because you "don't care" about the values right now, nothing stops the next developer (including future you) from needing the values. So now you've gone from not caring to "enabling someone to shoot themselves in the foot" if they don't read the types of the parameters carefully. That's the difference.
- eyelidlessness 4y agoThe case I was trying to convey doesn’t narrow the actual type for anything outside its own function body. Any footgun that exists after the function call already existed before it. It just implies “I’m only looking at your keys not your values”.
- TheCleric 4y agoI gathered what you meant. My point is what stops the next developer working on your codebase from adding code in the body of your function that accesses the values of the object in an unsafe way?
- eyelidlessness 4y agoA bit of trust. I’m not aware of a type system that protects my coworkers from my bad decisions, only those humans do that.
- consilient 4y ago