I found sweet spot for myself - flow with types in comments. As weird as it sounds it works for me on quite complex projects very well. Unlike typescript, which is language transpiler like coffeescript - flow is just typechecker with guarantee that after stripping types the output is valid js. It wouldn't work with ts, which generates runtime code ie. enums etc. Very good type inference means types appear as type declarations and when declaring functions and pretty much nowhere else. The code has interesting haskell'ish feel to it, ie. most of the code looks something like this:<p><pre><code> const ofId /*: (Sql, number) => Promise<User> */ =
(sql, id) =>
...
</code></pre>
I'm very happy with it after using it on quite complex projects, writing libraries (ie. functional combinators for parsers, assertions/runtime types, template sql generators; and the rest from apis, business logic to anything that is needed).<p>Lack of libdefs is not a huge problem in my case. I have strong preference for shallow or no dependencies in projects and for things I use 3rd party code there are types or were converted from ts or simply added. Better support would help here but it was not a deal breaker.<p>Code editor support is not as good as ts but it does the job.<p>Another interesting effect is that arbitrarily deep npm linking is so much easier, the code is just js, doesn't need transpilation step, can be edited as is; I'm free to use any directory structure, ie. I often use root directory to drop files, they have natural require/import paths, no configuration etc.<p>For me, it's a joy to code like this.