Hacker News new | past | comments | ask | show | jobs | submit login

"You don’t know if there really is a tool in place to check them."

Every project I interact with that uses type hints runs mypy as part of CI - and I can see that they're setup to do that by looking at the CI configuration (which these days is usually done using GitHub Actions).

I wouldn't add type hints to a project without also configuring mypy for it.




I work on a project that uses type hints but not mypy. To be fair, we used to use mypy, but there was just too much code that it couldn't check (sqlalchemy models, schematics models, some custom models, essentially lots of different data-modelling types!) Maybe it's improved since then, but it just wasn't mature enough at the time.

However, type annotations still make the code so much easier to work with, because they serve as documentation and are understood by the IDE. When I hit "." I actually get correct autocompletion because of the type annotations. When I want to know what a function returns I don't need to dig through multiple levels of function calls.

The article seems to be suggesting that because the type annotations might be wrong that they are worthless, which seems like a ridiculous argument. Any documentation can be wrong, but clearly having documentation that is 99% accurate is better than not having it at all.


I've found that it's pretty easy to slowly enable mypy checking. You can mark modules with "type:ignore" to make mypy ignore them. Then, you can move to marking individual statements with "type:ignore". Finally, you can start marking modules with "mypy: disallow-any-generics" at the top. That requires that functions are annotated with types.

In a large code base, our team has found type annotations and mypy to be quite helpful. If you are writing a quick-and-dirty script, forget about wasting time with type annotations. However, for long-lived and important code, it seems to be worth adding the types.

Another thing I noticed, if your type annotations are hard to write, e.g. lots "Union", "Optional" or deeply nested type expressions, it's probably a sign that your code is poorly designed. Think about what types you actually want to consume and return. Define new containers using dataclasses or attrs to keep the types simple, if required.


Right - I mean we had mypy passing across the whole project, but it just wasn't detecting any issues because so many of our types had to be ignored because mypy didn't understand that the runtime type of a Column field in SQLAlchemy is not Column, and things like that.

Rather than maintain all of the mypy stubs for no benefit, we decided to just scrap mypy.


> You can mark modules with "type:ignore" to make mypy ignore them.

If I added MyPy to the CI/CD checks, some coworkers would flood the code with these to not have to think about their typing. Too bad that some libraries like SQLAlchemy make this mandatory sometimes. I'd like the option to ignore these "type:ignore", but the type system is too immature and has to be overridden sometimes.


I disagree with your last line, especially for Optional (Union in python is basically useless IMO).


Isn't `Optional[T]` just sugar for `Union[T, None]`?


Touché. I guess a common pattern I find myself doing for Union types is having if statements checking if something is of a type using reflection. When checking if it is none, it is more elegant.


There are still a lot of libraries without hints, so mypy has to be told to ignore them in the setup.cfg file. Last I checked, sqlalchemy still isn't so good with mypy. So we have it ignored. But mypy is still great overall.


MyPy isn’t the only checker of course, there’s also Microsoft’s Pyright, among others. Pyright is fast and natively integrated in Microsoft’s Pylance VSCode extension, so these days I use Pyright’s type checking in real time even when I can’t be bothered to set up MyPy (no difficult, just not important for, say, <1000 line scripts). I default to strict mode for stuff that’s not too dynamic.

https://github.com/microsoft/pyright

https://marketplace.visualstudio.com/items?itemName=ms-pytho...


Precisely. We don't merge unless the result passes mypy.


We use pre-commit and you can't even commit until it passes mypy. It can be a bit frustrating sometimes, but overall it has saved us from a lot of issues.


I like the validation scripts being available in a repo so I can run them locally before pushing to CI, but I also often use WIP commits and quick fixups and then rebase before opening the PR, so pre-commit hooks are really annoying to my workflow. I more often than not just do `git commit --no-verify` or simply delete the git hook in `.git`, then just run it myself before pushing. Anyway CI will catch it, so I don't see much value in forcing it on individual machines.


This has been my experience as well, as someone who added a pre-commit hook (black and mypy) to a repo in lieu of adding it to CI (it was a while ago). I came back to the team a year later to find that everyone had simply disabled the hook, and forgone typing/formatting entirely. A day or two of fixing formatting, type hints and linting errors later, the CI pipeline had a new step enforcing all three :)


Our CI pipeline actually just runs `pre-commit run -all` on the repo too. So we know if someone doesn't have it turned on. But I could definitely see taking mypy out of pre-commit, and having it just be a CI step. Rather than waiting the minute on the commit to happen.


Yeah, when you just want to add a checkpoint WIP commit its annoying. Hate having to fight with that. But it prevents people form submitting a PR and then just having CI fail anyways. I could see it being nice to only enforce on CI though. Sucks seeing those red builds because someone didn't run something manually.


I don't see it as a big issue as we just assume PRs with failing builds not to be ready for review and push them back to draft. But whatever works for your team, honestly. In the end what matters is having a CI acting as authority source, the rest is simply workflow related.


Yeah, think its just a difference in mindset. Some teams strive to never have failed builds, while others don't care because its all part of the process. I think we were more in the mindset of you should never push a failing build initially, but have moved more towards its all part of the process.


Yes. The reason type checking is separate from the interpreter is that python is an ecosystem, not a language. Even if you like static typing, 99% of projects benefit from other code that lacks typing. Type hinting puts you in control of where types are enforced while allowing you to use duck-typed code. The cost is that you have an extra step in your build chain - but CI, IDEs and other automation all but negate that cost.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: