I’ve ran into situations where pretty obvious “if (typeof + condition)” chain over-narrowed a type so that further else-ifs were inferred as “never”. The logic was sound and triple-checked, I only struggled with convincing tsc that it’s okay. Sure, it was my fault somewhere in my types and not in typescript, but the progress doesn’t care which part of a development site fails or spends too much time in research.
unidiomatic js trickery
type Foo = undefined | false | Unit | Foo[] | FooObject
This was a part of the issue, afaiu. FooObject being “partial” either fell through obvious typeof guards, or removed other essential types from a branch, depending on what I tried. I ~understand why the issue persisted, but had no clear way to tell tsc what I mean there. The perspective to meet a similar issue in a much more complex case feels unpleasant.
While types make intents formal (which is a pro), they require to specify irrelevant edge cases. Dynamic typing serves as “code is law”, and when you meet an edge case in the wild, it’s much easier to explain it than to formalize.
I also remember many cases of prototyping in other typed languages and it never felt “focused on the job” to me there either, even when (or despite?) a type system wasn’t turing-complete.
Also, my best hope for typescript was that it would allow me to create type-only “header files”, which would serve as a source of truth and a sort of auto-validated documentation. It turned out that forwards are not first class citizens in ts, and it was sunday evening already, so I gave up.