I tell my fellow developers at work: "Any is banned. If you want any, use JavaScript, and we don't use JavaScript here. Perhaps you haven't heard about unknown?"
In my experience, 90% of the time when a developer uses any, they just don't know about unknown. 9% it's because they are lazy. 1% is because you are implementing something from an imported library, and they fell into the other 99%.
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.
The 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.
If 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.
Use "unknown" and TS complains that you're treating something as an object.
Use Object.defineProperties and TS complains because that stuff is invisible to it after how many years?
I think you're right, of course, but TS is hardly perfect and treating its ways as gospel is not an improvement over JS. The "right ways" change over time and beliefs are not shared among everyone.
If you know what's in the object cast it as that type or be sure by saying if ('propertyName' in unknownObject).
TS is far from perfect. These aren't its ways (it provides any, so of course it's fine with it). These are my restrictions: if you're using a type system, actually use it. Don't lie to yourself and throw anys in your code.