The things Typescript gives you are very physically visible and so, gives the illusion and confidence it will guard you in everything but in reality it helps in the most trivial of problems and you are paying a big cost for it.
If people are saying the type system is a magic bullet, the problem is with that claim and the people making it, not with the type system.
That summarizes it. But to understand what it means usually takes at least 10 years and most people will never understand it.
My best interpretation of high cohesion is that it means that every component/module/class in a system can be easily explained to a non-technical person who has business/domain knowledge... In as few words as possible.
Loose coupling requires simple interfaces. Simple functions/methods which accept simple (raw primitives or plain objects) as arguments... You want to avoid methods which accept 'live instances' as much as possible. Instances which have their own internal state should not cross module boundaries ideally (not passed around as arguments). That is also a sign of low cohesion. High cohesion and loose coupling often go together naturally. For loose coupling, I often think of a power plug/power point or a USB port... Simpler is better. Imagine how difficult it would be to plug an elaborate 10-prong power plug into a socket with 10 holes... Imagine how much work that would be for the electronic equipment manufacturers. The interface must be as simple as necessary to get the job done.
If you can do these two things, it will constrain how you think about and write code and you will produce the most maintainable code you can imagine. The language won't even matter at all. If your method interfaces are simple (no complex type parameters), it becomes trivial to figure out which types a specific methods accepts as arguments.
IMO TypeScript makes it easier to work with bad code, but isn't a better solution simply to avoid bad code? It's not that difficult once you have the right approach.
In a way, I feel like TypeScript is a symptom of the entire industry surrendering to bad code... A surprising number of people in the corporate sphere actually believe that there is no such thing as good code and even that architecture, software design and planning doesn't matter. The only solution they will accept is to throw more people at the problem and implement security through obscurity.
Imagine how difficult it would be to plug an elaborate 10-prong power plug into a socket with unknown number of holes.
With static typing, you at least know how many holes are there.
Now, I agree that "the interface must be as simple as necessary to get the job done", but non-trivial problems will have non-trivial essential complexity even after you have removed all incidental complexity.
E.g.
People today have terrible handwriting because of computer keyboards.
Many people today can't do long division on paper because of calculators.
People today struggle to find their way around new places when they don't have Google Maps.
But in this case, the skill which is being atrophied is an actual useful skill... Though it's not obvious at a glance. A tool which makes it easier to do the wrong thing will lead more people to do the wrong thing.
The friction which dynamic languages create is a positive and promotes good code and professional development.
If friction was "positive and promoted good code", the best code would be on punch cards.
Exactly. That's why TypeScript is structural typing with inference. The industry has given up on teaching developers how to organize code. The only way to force everyone to play nice together is through tools: prettier, VSCode, TypeScript, lint, etc. etc.
Part of me thinks this is a social problem. Too many unmoored egos in the industry and no one in the social position of being able to lay down ground rules for a codebase. Or possibly a result of devs chasing higher salaries and becoming mercenaries always on the move. It's rare to have teammates that have been with a company longer than a year anymore.