You Should use Type Checking on your Python code
If you have been programming (in Python) for some time you must know this feeling: you write some code, run it for the first time, and it fails on a dumb mistake. But there is a way to get it to run first try.
The Problem
If you have been programming (in Python) for some time you must know this feeling: you write some code, run it for the first time, and it fails on a dumb mistake. You fix it, try again, and you get another dumb error. And again, again and again. Finally, after a not insignificant amount of time, your code runs.
And the issue? Maybe you forgot to cast a string returned by an API into an `int`. Or a dictionary key you were so sure existed was actually named slightly differently. Or you forgot to return from your function and got None
instead of the list you wanted. Simple mistakes that cost you significant debugging time, over and over.
The worst part is that none of these are algorithmic problems or architectural challenges. They're not the kind of interesting puzzles that make programming interesting. They're just type errors. And then you go "Of course...", fix it, and run your code again to find the next one.
Python's dynamic typing is powerful. It's one of the reasons people love (or hate) the language. It lets you move fast, and also, break things. And that last part sucks. Because it's often avoidable. Should our code reviews be filled with "Remember to check if this value can be None"?
The Solution
There's a better way. Type checking.
Type checking allows you to be explicit with your code's expectations. It's declaring that this function takes a string and returns a number. That this list should only contain dates. That this dictionary maps strings to user objects. That this method returns the same type as its input. And it finally gives you that feeling of your code working first-try.
"But Python is Dynamic!"
Yes, Python is a dynamically typed language, and that's part of its charm. The ability to quickly prototype, the flexibility to handle data in creative ways, the elegant syntax that doesn't get bogged down in type declarations. I get it. I love it too.
But here's the thing: adding type hints doesn't take any of that away.
This isn't about turning Python into Java. It's not about adding bureaucracy to your code. It's making your intentions clear, and helping others (or future you!) understand your code better.
"But it will slow down development!" I used to think that too, until I realized how much time I was already spending debugging type-related errors and writing defensive code.
The truth is, we're already thinking about types, hoping we don't forget anything, and paying the price when we inevitably do. So if we already spend time thinking about it, let's invest some more time to make all that thinking actually matter.
Type Checking: The Best of Both Worlds
Think back to that frustrating debugging session we talked about earlier. Now imagine this instead: you write your code, and before you even run it, your editor highlights the problem. "This function is supposed to always return a string, but it might return None in some cases." Fixed in seconds. No runtime surprises, no stepping through debuggers, no facepalm moments.
That's what modern Python development feels like with type hints. Following up on that example, check the following code out:
def get_user_greeting(name):
if name == "admin":
return "Welcome back, administrator!"
elif name == "guest":
return "Welcome, guest!"
print(get_user_greeting("admin")) # Welcome back, administrator!
print(get_user_greeting("guest")) # Welcome, guest!
print(get_user_greeting("user")) # None
# Function with declared return type "str" must return value on all code paths "None" is not assignable to "str" (reportReturnType)
This code looks correct at first glance. It runs fine during happy-path testing. But when you input something unexpected, everything breaks. You thought it would give you a string - but it gives you None
With type hints, these oversights get caught before you run your code.
Here is what makes type hints great:
- They're optional - use them where they add value
- They're gradual - add them at your own pace
- They work with your IDE - get better autocomplete
- They catch errors before runtime
- They serve as living documentation
And the Trade-offs:
- Performance: Type checkers like mypy can be slow on large codebases
- Learning curve: Your team needs to learn concepts like generics (though you can start without these)
- Maintenance: You'll need to keep type hints updated as your code changes
But in my experience? The time saved on debugging makes up for these challenges.
Real Talk
I love seeing how bigger companies handle this. Dropbox's journey is particularly telling - they went from having millions of lines of untyped Python code where, they said, "understanding code becomes the key to maintaining developer productivity", to successfully type checking 4 million lines of code. The benefits were so clear that they actively help develop mypy (a popular python type checker) now.
And what were they struggling with before types? Questions that might sound familiar:
- "Can this function return None?"
- "What is this items argument supposed to be?"
- "Does this argument need to be a list, or can I give a tuple?"
But you don't need to be at that scale to benefit. As Dustin Ingram points out, type checking shines when:
- Your code is confusing (we've all been there)
- Your code is for public consumption
- You're about to do a big refactor
Making the Switch Without Pain
What about all your existing code? Nobody wants to face thousands of errors just to start using better tools. After experimenting with various type checkers, I've found basedpyright to be the most pragmatic solution.
What won me over wasn't just the better defaults or improved CI integration - it was the brilliant baseline feature. Instead of being bombarded with errors from legacy code, baseline lets you focus on what matters: keeping new code type-safe. Your old code stays quiet until you actually need to modify it.
This isn't just another "ignore all problems" approach. Unlike the usual practice of sprinkling ignore comments throughout your codebase, baseline provides a clean, systematic way to improve type safety gradually. The errors don't disappear - they're tracked and automatically resolved as you naturally improve the code over time.
The Future is Typed...
The Python ecosystem is rapidly moving towards embracing type hints. FastAPI was even built from the ground up around type hints, becoming one of Python's most popular frameworks, averaging around 1.5 M downloads per day. Dropbox's success with mypy has proven it works at scale. The tools are getting better every year, with options like basedpyright making adoption painless.
The Python ecosystem has increasingly embraced type hints over the years - they've been officially supported since PEP 484 in 2014, adopted by major projects like FastAPI and Pydantic, and according to the 2024 Python Typing Survey, 91% of respondents use types "Always" or "Often". While they remain optional (which is very Pythonic!), they've become a mainstream part of modern Python development.
Modern frameworks expect them, IDEs understand them, and developers are realizing they don't have to choose between Python's simplicity and type safety. Python isn't Java, and never will be. Python's type system is gradual and optional - you use it where it adds value, not because you have to. And that's exactly why it works.
Now What?
You don't need to be Dropbox to benefit from types - I've seen the benefits in projects of all sizes. Start small, maybe with that function that always seems to break in weird ways. Each type annotation will make your code a bit more maintainable and a lot easier to understand. Your editor will thank you, your colleagues will thank you, and future you will definitely thank you.
Resources
- Official Python Typing Documentation: The official typing module docs are a great reference
- Basedpyright Documentation: Comprehensive guide to my personal fav
- FastAPI's Tutorial: Even if you're not building APIs, their tutorial is an excellent practical introduction to type hints
- Awesome Python Typing: A curated list of typing resources, articles, and tools