I’m currently going through this at work and my experience even with smaller packages agrees with the author: After trying it the loose way and failing, I realised the best way to proceed is with maximum strictness from the start, converting the .js files to .ts in dependency order. When a file is converted from .js to .js, it’s almost guaranteed to be 100% converted. There are probably some edge cases where some refactoring necessitated by the conversion propagates to its already converted dependencies, but I would expect those to be minimal.
I wish mypy was the same. I’ve tried to add typing for our fairly large (100k+ LOC) python libraries 3 or 4 times now and failed every time. One of the big issues is strict isn’t well supported, and some libraries and frameworks just do not play well with typing or have separate half baked stub libraries. I also firmly believe it should integrate seamlessly with e.g. pre-commit, and that hasn’t been my experience either, with special workarounds needed for the pre-commit hook to perform identically to running it in the locally installed venv.
So we just write new code with types by convention but have no actual linting or checks because it’s too hard to actually static typing to an existing repository.
1. Give up on pre-commit. It would be nice if it just worked, but it doesn't. Just make a type checking script and run it as the first thing in CI.
2. Use Pyright, not Mypy. It's much much better.
3. You can start with a very loose config and gradually make it stricter.
4. Make liberal use of `type: ignore` (and add TODOs to make it clear they're not intentional).
5. You can also make an alias for Any and use that for types that you intend to figure out but haven't yet.
Typing Python that wasn't written with type hints in the first place is always going to be a complete nightmare though. People that write untyped Python tend to write it in highly dynamic ways and Python's type hints often aren't expressive enough to describe them (e.g. they only very recently added support for properly typing kwargs).
> Typing Python that wasn't written with type hints in the first place is always going to be a complete nightmare though
Couldn’t agree more. I joined a new team and recently finished converting a 20K line repo. It was a grueling grind to get mypy running in strict mode.
I’m continually finding that a huge benefit of typed python code isn’t autocomplete or catching bad argument passing, but preventing developers from creating patterns that are unmaintainable.
If your code is too complex to type correctly, its probably too complex in general :)
> If your code is too complex to type correctly, its probably too complex in general :)
Ha I definitely agree with that. There are some exceptions where you want to do a reasonable thing that the types just aren't expressive enough for, but in general if you can't explain it so the type checker understands then your coworkers won't either.
> 1. Give up on pre-commit. It would be nice if it just worked, but it doesn't. Just make a type checking script and run it as the first thing in CI.
I’ve been slowly reaching this conclusion after a few years of running into little issues. We run our pre-commit hooks as their own CI test via tox. I’m beginning to feel both tox and pre-commit are more trouble than they are worth, and most of that trouble comes from them trying to create and manage their own mini-environments. Which is never going to match having explicit envs, state, and deps via docker files that can be granularity inspected and/or deployed to other contexts.
> 2. Use Pyright, not Mypy. It's much much better.
Does this work well with pycharm? I think I looked into this a while ago and it seemed really tightly coupled to VSC. And I know some people love it, but I’ve found VSC’s config for linting/type checks/ auto formatting to be a complete confusing mess, and that it is generally much slower and buggier than pycharm (e.g. it will highlight errors that don’t exist, not update syntax highlighting instantly, etc).
I know it’s entirely possible that it’s just me who is an idiot here, but I’ve set up VSC on like 3 separate machines now in the last few years and it invariably ends up in some weird broken state, especially regarding highlighting code performantly and correctly using the same rules we have in CI.
Nah pre-commit is great for lots of quick checks (formatting, trailing whitespace, linting shell scripts etc), it's just that type checking Python requires the Python dependencies to be already installed and that means setting up a venv and installing stuff and that's just a bit too complex.
> Does this work well with pycharm? I think I looked into this a while ago and it seemed really tightly coupled to VSC.
Possibly not. You can definitely run it from the command line without VSCode since Pyright the type checker is open source. The VSCode Python LSP server Pylance is closed source though (this provides additional features beyond type checking like completion and refactoring).
Haven't used Pycharm for decades but I'd guess it has its own thing.
While I have never done a js to ts conversation, trying to modularize a ts monolith into even some rudimentary packages was very difficult because of circular dependencies at the file level
(which is entirely possible).
Ended up giving up at the time because of cost/benefit.
In one of our single-package repos, I added some ESLint rules to effectively forbid circular module dependencies. Not only are they a code smell, but when modules have side effects (which is really common), they can break circular dependencies at arbitrary places in the cycle.
We’ve been gradually moving to a very small number of monorepos and can better achieve modularity by liberally creating small packages and forbidding package-level cyclic dependencies.