I do not agree that typing leads to less cognitive load.
Typing often leads to more and more complicated code.
Dynamically typed code is often shorter and more compact.
If dynamically typed code is well written, its function, inputs and outputs are clear and obvious.
Clear and easy to understand code is not primarily a matter of typed or not typed code, it is a matter of a great programmer or a poor one.
In a dynamically duck typed language it should not matter if an ID is a string, a number or a GUID. The code should work with all of them. The semantically important thing is that this is an identifier. No String, number or GUI data type expresses this true meaning of the value.
If there are multiple types of user IDs, I don't want to pass the wrong one into a DB call.
This is often the case when dealing with systems that have internal IDs vs publicly exposed IDs. A good type system can correctly model which I have a hold of.
For complex objects proper typing is even more important. "What fields exist on this object? I better check the code and see what gets accessed!"
Even worse are functions where fields get added (or removed!) to an object as the object gets processed.
Absolute nightmare. The concept of data being a black box is stupid, the entire point of data is that at some point I'll need to actually use it, which is a pain in the ass to do if no one ever defines what the hell fields are supposed to be laying around.
By naming the variable ID it is crystal clear what the value is.
Most of the time an explicit type only adds cognitive load to the reader, and limits the universality of the code. At an high abstraction level, most of the time a type is from a program logic point of view an irrelevant machine implementation detail. If a specific duck is required it is explicitly tested. This makes code very clear when the duck type is important and when not.
Statically typed code definitely requires more effort to read, but this is not cognitive load. Cognitive load is about how much working memory is required. Statically typed code requires less cognitive load because some of the remembering is outsourced to the source code.
Statically typed code can lead to more complicated code; it can also accurately reflect the complexity inherent in the problem.
I split local reasoning into horizontal or vertical.
Vertical reasoning is reasoning inside a module or function. Here information hiding and clear interfaces help.
Horizontal reasoning is reasoning across the codebase in a limited context; adding a new parameter to a public function is a good example. The compiler helps you find and fix all the use sites, and with good ability to reason vertically at each site, even a change like this is simple.