Real unit tests (not integration tests) are poor man's types. Usually when you have very small unit tests asserting inputs and outputs of methods you would simply assert those with types in more powerful languages
Haskell has pure functions everywhere and a much stronger typing system than TS, but unit testing is still considered important.
Someone else will be changing that code later. Knowing (for example) that the parameter is a string will be zero help in knowing what is being done with that string. It also won't help know what edge cases the code was handling.
Also, types give a false sense of security. A new project was integrated into an old website (one with legacy dependencies, but doing millions in transactions every day, so unchangeable).
It broke and they couldn't figure out why. They had the TS types for functions, but an old framework (prototype or moo iirc) overrode js built-ins with incompatible versions. Later they got bitten again when that code changed the object types. If they'd been writing js, they would have written dynamic checks from the start, but it's easy to forget that once you compile, it's just js.
You can always describe what has been done with the string by boxing it into an expressive type. Your other example is that when dealing with bad external code you need to do additional checks. That's a specific scenario and every language which exists has to deal with it in the same way. In more powerful languages you could infer which checks need to be done from the type and do the automatically for external code