Ty mypy: The New Generation of Python Type Checking
Ty is a high-performance Python type checker developed by Astral, designed to address the performance bottlenecks and ergonomic issues associated with MyPy. While MyPy remains the industry standard, it often suffers from slow feedback loops, noisy error messages, and a complex configuration process involving nearly 100 options. Ty aims to replace these pain points by providing a faster, more intuitive experience integrated directly into the development workflow.
The tool is implemented in Rust and utilizes the Salsa framework to enable demand-driven computations and efficient cache invalidations. This architecture allows Ty to perform significantly faster than MyPy; in benchmarks on the MyPy repository, Ty completed checks in 700 milliseconds compared to MyPy's 21 seconds. Additionally, Ty includes a built-in Language Server Protocol (LSP) implementation, providing immediate IDE feedback, smart imports, and detailed error diagnostics that reference function definitions and types across files.
Technically, Ty diverges from MyPy by distinguishing between Any and unknown types, which supports the dynamic gradual guarantee—the principle that removing type annotations should not introduce new errors. It also implements set intersection types, allowing the checker to infer not only what an object is, but also what it is not. However, Ty currently lacks a plugin system, meaning it cannot handle the dynamic type coercion used by frameworks like Pydantic or SQLAlchemy.
For adoption, Ty is recommended for greenfield projects or as a local development tool to provide instant feedback, while MyPy is suggested for CI pipelines to ensure strict correctness.
This description was generated by Open-Source AI using the transcript of the session and the original submission contents.
This session took place in track Python Language & Ecosystem and was classified suitable for intermediate domain / intermediate python by the speaker.
Submission
The proposal as submitted by the speaker before the conference.
Static typing in Python has matured significantly over the past decade, with mypy becoming the de facto standard for many teams. At the same time, developers continue to struggle with slow feedback loops, noisy errors, and friction in CI and local workflows. ty, a new type checker from Astral.sh, aims to address these issues with a fundamentally different set of design priorities—and it has now reached a post-alpha, production-ready stage.
This talk takes a practical, experience-based look at ty from the perspective of a Python developer using it on real code. We’ll start by briefly reviewing the current state of Python type checking and the problems that motivated ty’s design. From there, we’ll dive into ty’s feature set, performance characteristics, and developer experience, focusing on what actually changes when type checking becomes fast and ergonomic enough to feel “always on.”
A central part of the talk will be a direct comparison with mypy: where ty already excels, where it behaves differently, and where mypy remains the better choice today. Rather than framing this as a replacement story, we’ll explore the trade-offs between the two tools and what kinds of teams benefit most from each.
By the end of the session, attendees will have a clear mental model of how ty works, how mature it is today, and whether it’s a good fit for their own projects. More broadly, we’ll look at what ty signals about the future direction of Python’s typing ecosystem.
Transcript (auto)
Auto-generated from the recording utilizing Open-Source AI. Speaker labels (Speaker 1, Speaker 2) reflect diarization, not identity. Timestamps refer to the recording.
Speaker 1 [01:17]
In the introduction, my name is Stefan Kraus. I'm a data engineer and ML engineer with a strong background in traditional Python software development. And I'm located in Erlangen. That's a small city in Bavaria, Germany. And I'm writing Python for literally half of my life, which is still a very long time. And I've seen a lot of phases this language is going through. I've seen the good phases, the bad phases, the interruptible phases. and I've really often felt the pain of bringing it into production in a really nice scalable way and I'm using MyPy pretty much since it was published and I want to be clear this is not planned as a MyPy bash talk because bashing something is easy when you can't do it better so I want to be showing you an alternative tool that may be better for your use case But I'm really, really thankful for what MyPy did with Python and the community in the last 10 years. But before we start, a few words about the ones who pay my bills. I work at InnoVEX. We are an IT project center that partners with customers in whole Germany. We provide highly skilled experts to their teams and build their digital products together with them. So, in case you need any help with infrastructure, software engineering, data engineering, and so on, we probably have one expert. We are now approximately 500 tech heads overall in Germany and newly in Switzerland with a strong Python shop. Around this conference, we have 20 InnoVEXers running around, six of us give talks, and in case you are right now looking into some new opportunities or need help with your current projects, just grab someone from us and let's talk to it. Enough advertisement, let's now start with a short overview about what we do today. We at first discussed the MyPileLegacy, what happened in the last 10 years and why we have maybe some issues that we want to tackle with new tools. Afterwards, we look into the Tide design philosophy that's shared among other tools as well, look into some features with actual code, how MyPy behaves, how DY behaves, and afterwards to honest comparison. Can we just replace it? Is it better? Is it worse? And a verdict on my opinion based if you should change or not. Good. Let's start with MyPy and the legacy. So MyPy is quite old but still the de facto standard. In a report from Meta last year, It's shown that approximately 60% of engineers that use type checker in Python are still using MyPy with a few percent less against PyWrite. All the alternatives are more or less percentage taken. MyPy was initially created by a guy like Yuka as part of his PhD research project after some previous work on typed languages and later continued at Dropbox, the big file share company, where also Guido van Rossum himself worked at that part. And one has to say, the idea from Jukka was great, but he had not a lot to work with. Let's look at the code we see on the right side, the upper one. Before we had the nice typing path and all the nice specifications, there was not a lot to work with. We already had this colon syntax, we also had the return value syntax, but these were not specified to use with typing at all. So you could technically do whatever you wanted, so people put also in documentation or whatever they want to. There was no rule what they were out for from Python 3.1. But after the years and the success from MyPy initially, Python needed to change. Guido, Jukka and others wrote down the PEP484, which then revolutionized the typing system in Python, introduced a a lot of new features over the time, for example this nice typing module in 3.5, part of the initial pep, new type also part of it. We have this nice colon syntax, the nice pipe syntax for unions in 3.10 and a lot more. And if you look back in the history, I think there was no version in Python starting from 3.5 which has not any form of improvements typing in the introduction, even in the newer versions. But with 10 years of legacy and when you really need to start building it up at first, there are things that are just getting a pain point or already were a pain point. So the typical things one hears is, well, my API is slow. Yeah, the slow feedback loops are a big issue. It takes seconds, maybe a minute on a big code to actually get it started if you don't have a cache. Then you don't have things like a language server protocol. Also just because the language server protocol was not there in 2012 where MyPy arises. So there are solutions for demonized MyPy, but these are really patched on top and not built really in the checker itself. And as we've seen with the hands before, the errors are quite noisy. noisy. You get error messages that are hard to trace, hard to understand. And if you try to fix them or configure the MyPy type checker itself, well, there are nearly 100 different options to read and decide on. So this is just complex for a lot of users that just want to have a type checker to help them. And these are not just minor inconveniences. These are real blockers that change how you work with this tool. This will come back later, but this is really something that disturbs how you interact with the tool. And then, especially in the last few years, things changed in the Python ecosystem. And if you pay any attention to the ecosystem, there is this one company, Astral, that has just the habit of completely disturbing what we work for by just building it in Rust and building it very, very good. So we have seen the success of Ruff in August 2022. So pretty much Black, iSword, Flake, and everything that you had before and need to configure GAN in a single tool. Two years later, you'll be the pretty much de facto package manager you use today, especially when you have a new Greenfield project. And in the same years, they started with something that they internally called Red Knot. which they then announced at alpha state as TY on a blog post. And at this point, when they looked into it, they really disclaimed, hey, this is very early alpha, there will be changes, do not use it in production. They also had no pre-commit hook and actually said, no, please do not migrate right now, this is not stable enough. But then at the end of the year, Charlie Marsh wrote a blog post on the Australia website that clearly states, okay, we have an extremely fast Python type checker and language server with the actual call for action that they exclusively use it in their own projects and also motivate others to use that. Okay, that's a nice and easy thing to say when all your projects are in rust, right? but um there happened a lot in the meantime right now and i have to say it did not check it today i think we are at 0029 right now at least we were yesterday evening and still in better um so very careful but they planned a release for this year so at least a 0.1 release and now the big question why should people rip out a well-used tool that kind of much works for something that is right now in a better release let's look at that in the next few minutes and tie is built on three fundamental pillars and i put in quotes that are also from the blog post first thing is it's built with and for the community so the astral has its core team alongside dozens of actress contributors. That's at least the plan. We look into that. Then, very shortly stated, tie is very fast. We'll see how fast it is. And, and that is the most important point, they want to build a correct but also ergonomic type checker. So it should not be perfect, but it should be in a state where it's usable for all developers without fighting a lot of issues or weird error messages because in the end, the tool should help us, not fight us. Let's go into these three pillars. The first one is quite simple. And if you are a bit in the GitHub or ecosystem around, it's the classic astral behavior we've seen here. They have an immense community traction. When they release something, Reddit goes crazy about what they did again. So the TY repository itself, which does not contain the code, alone has 18,000 stars. The rough repository, which now contains the code, has approximately 50,000, which are only a few projects that have that much. Also looked into it, and while it's built by a core team from Astral, still 25% are contributions from external contributors, so independent persons not paid by astral with approximately 120 unique contributors alone in this year and that is for our open source project that's hosted by a company a lot i think second it's open development we have a nice mit license everyone can use it without paying for it they They really welcome the contributions from the community, not only as a site, but also with active contributions and feedback. And they have a very low ground to get started with. They have a nice playground of which you just want to see how it behaves. You can go on this website and play around how TY would behave on a specific code example without needing to install it. numbers, iteration development is crazy. The velocity is crazy. It was super hard to keep up with their features during the presentation just because they do right now two releases per week with bug fixes with other things and so. Okay, community done. Let's look if they can keep their promise on a really fast type checker. For that, I had two different setups running. The first one is, well, what happens when I just check out the MyPy repository itself and check how MyPy behaves on that from a timing perspective. So I did that without a cache. Did you rerun? That's pretty much the same line they do for their own benchmarks, and it takes approximately 21 seconds. So this is the wall time. The same repository without any cache and so on takes only 700 milliseconds on TY. So we are talking about 30 times more with MyPy. And that, I think, is really crazy. Secondly, I opened up a function in VS Code to see if also an iterative, an incremental load, it gets better, picked up a function that's imported nearly 100 times about the files, changed it, And also here, TY was just ridiculously fast at regenerating the error messages. So we have one-fourth of a second for TY and nearly two seconds for MyPy. And that really changes how you write and behave when you type code. Now people obviously ask, okay, why is this so fast? I mean, 30 times more runtime for MyPy than for TY. There must be something. Well, there are different reasons for that. The first one is pretty, pretty simple. It's Rust. Rust is fast. That's no surprise to anyone in this room, I guess. We don't have to hold overhead from keeping a Python interpreter running, from needing to start the Python interpreter at all. So we can just execute directly on bare metal and it works out of the box. That's just faster. But also what they do is different. So they use the Salsa framework. It's the same framework that powers the Rust analyzer itself. I'm not sure if any Rust experts are here. They will maybe know a bit more about that. In short, it's demand-driven computations with very smart cache invalidations. So they keep track of all the heavy lifting in the background, so these analyzations are just faster. Besides that, they also do fewer checks. They cache on different levels or recompute only what's needed. For example, in MyPy, when you change the body of a function, like func b, it still checks the whole module, so the whole file with MyPy if you don't use the daemon mode. And in TY it checks, okay, if you change the body of a function, most of the time this had no real effect on the rest of the file, so I'm also not going to change it. And that actually changes how you behave with the tool. Because when a type checker takes 20 to 40 seconds for a check, you don't use it as a type checker. It suddenly gets a compiler. You start coding, you start more, you batch a single run of the type checker, you go in, you start to fix things, you lose your whole context, and so on. You need to rethink and restart from scratch after writing code. When the type check runs immediately, you do not leave your context at all. You write your code, you get instant errors, you get fixes, You continue writing code and you're just in the right loop without losing this context, which is the most pain normally you have. All right. Cool. Speed is done. Let's now talk about features and the completeness. The first major difference between MyPy and TY is how it handles untyped code. So as long as everything is typed and you behave like a strict language, everything is good. As soon as you have untyped code, it gets different. Because mypy keeps any and unknown as the same. But semantically, these are different. Any is an explicit command you write. Any means I don't want to have typechecks right now. I want dynamic behavior. Please, typechecker, you don't need to check that. I'm sure what I'm doing. But unknown is a state of information. Unknown means this has a static type, but you don't have enough information right now to determine it. So this is a list of integer or string or just a list. It will have a static type, but right now you don't know because the information comes in later. Let's go on the right side with the empty list pi example. This is a classic one that a lot of people, I think, have seen already and how these two type checkers behave differently. So, my Pi just sees the self-items assignment, sees that this is a list, has not any more context and just sees, well, I don't know what type this list has exactly. I'm going to assume any and I ran all my examples, all my projects in strict mode so I normally get this error message that says, well, I need a type annotation. You need to annotate that this is a list integer, a list this class and so on. Ty just says, well, it's a list, I have no idea what's in the list, so I'm going to keep that list unknown, and everything is good. And because these two things are separately for TY, it unlocks something that's called the gradual guarantee. That's a formal thing in typing theory that I don't want to go into too much detail, because that will bore you all to death, trust me. But the relevant thing that's interesting for us is the left quote. That's a part, the dynamic gradual guarantee, and that says, well, in a dynamic language, removing type annotations from code should not introduce any errors. So when I have a typed Python program and I erase the types, it should not break any other things. And on the right side, you see, and this is an opinionated thing here that's decided by TY or by MyPy, that when you run this code, in the second line, the append will suddenly determine that this list is an integer list and MyPy fails when you put in an apple. In Python, this is completely valid code, right? I can do that. And my type checker should normally not forbid things that the language itself thinks is correct. Can be discussed, but that is how the basic theory behind that works. All right, let's go into another thing. Because TY is also a way better mathematician than myPi is and we see it on another property that TY implements. And that is handling intersections of types as well with that theory from math. What does it mean? We know the pipe operator that says, well, a type is from type A or B. ty is having additionally an intersection type that says an object can be from type A and B, so even restricts that even more. We'll see that at best on the right side where we have a nice function getting in a UA element widget and we check in there with its instance if this is additionally a clickable element. Even if you use MyPy, you see in both cases that it's UI element and clickable. In MyPy, this is shown, but this is quite a hack because it's a synthetic type in the background that's temporarily stored and not further done. In In TY, you have real set intersection. That enables something that MyPy can't do, and that is also inferring what an object is not. So, in the else case, while MyPy only has the knowledge that is an UI element, TY also introduces the and not clickable that allows more strict types and finding more errors. One other thing, we talked about it, MyPy is meant as a CLI tool. Majorly, the whole iterative things are patched on top. TY has a language server directly built in, so whatever IDE you use, whatever is your favorite one, as long as it supports a language server protocol, which are mostly all IDEs Today, you get all the nice features like go-to-definition, smart imports, safe renaming, and very more. For example, on the right side, the user returning is an inline hint that my VS Code generated directly. And when I have a missing import, it also provides quick fixes. Error diagnostics are one of the major points where I say that TY is better than my peers. So, on the left side, we have a very simple cross-file reference issue where we pass in the wrong value on a type, and we see the different outputs from the two type checkers itself. Right, top one is just, here is the line API for it's wrong, there must be anything else, and that's good. And on the right side, you get so much output that it looks too small to really display on the slides we have. So you do not only get the line where the error happens, it references the function definition and the function type itself. So you do not only get, well, an admin editor is needed, but, well, the set role function is defined in this file, here is all the context that you need to get this one figured out yourself. You do not have to click around in your IDE to get it done yourself. And if an error happens, it's simple to debug for yourself. Cool. And that sounds lovely. And everyone here in this room wanted to directly install TY as soon as this talk is over. But unfortunately, the TY speed and the TY magic ends when the Python magic starts. And that is a bit sad. Let's look at a very specific example it happens in at least my daily experience. And that is type cohesion, especially with Pydantic. Let's look at the right side. We have a UUID and we know Pydantic automatically coheres to this type, and TY can't do that, unfortunately. MyPyCanDoIt has a plugin, loosens the constructor, everything is good. TY handles or only has the type information that's statically available. They also do not have a plan of a type system, of a plugin system, obviously, but they want to introduce support for core libs like Pydentic, like SQL Alchemy, and so on. and they disagree sometimes unfortunately and the examples are unfortunately also quite easy to find on the left side we just have a simple sum function Euclidean distance which in my pi suddenly says well why does it should return a float it returns any why does it happen Well, actually, the sum function has a start value of zero for empty lists, and zero, the literal zero, is an integer. Integer pow float is actually not implemented. It falls back on an rpo on float otherwise, and mypy interferes with any. Here, tie is just better. Tie promotes numbers, checks that everything is good. But sometimes TY is too relaxed. We know it. We load JSON. It returns any. TY says, well, there is an any. I trust you. You deactivated the dynamic behavior. I respect it. I'm not going to check that. So here TY allows you to do that. MyPy says, well, that's a bad habit. Don't do this. Let's speed up a bit. The verdict. Should you start using TY based on my experience? I would say it depends. If you have a Greenfield project, a very small team, try it out. I, in my experience, would say the LSP and the direct feedback that you have is it worth to spend some time into looking into TY. If you have slow monorail posts, so a lot of code and it just takes a lot of time for the CI, for your developers locally to run, run it in parallel. use TY locally with your developer set up and use mypy or keep mypy in your CI as a gateway. If you depend on heavy framework magic like Pydentic, things where things get really dynamic, hold off for now. Wait until the ecosystem changes and implements the pep681 which does data class transform. And if you depend on the correctness of your CI also So hold off. It's in beta. Wait at least until 0.1, we'll see if we ever get a 1.0 release at all. If you want to migrate or if you want to run it in parallel, do the following. The developers set up their end editors with LSP, local pre-commit hooks, and you don't touch the CI pipeline at all. You keep mypy here and if they disagree, just put in a type ignore. You can later remove them as well. Few short words to the end. Let's zoom out a bit. I have talked a lot about UI now, also because it's a talk about it. But we have to go a bit bigger because in case you were here yesterday as well, you You have heard about another type checker with a similar, which is Pyrefly from ETA. These tools have a lot in common, actually. Both are done in Rust. Both show that it's not feasible to wait on MyPy's results, and that the MyPy Python-based approach now just hits its limit on speed and correctness, and the industry is safe but it needs an alternative. The astral advantage, and why I picked this one, is the unified vision of the whole project. Yeah, they gave a froth as a standard tool. They gave us UV as now a standard tool. And now they come in for TY that maybe becomes a standard tool. And for the final takeaway, it's not just a drop-in replacement. Yeah, there are differences between MyPy and TY. But the signal is clear. We can't wait on long-running CI and long-running tools, especially in the time of agentic workflows. But they bet on developer feedback. And when I see what they did with rough and UV, this is a critical safe bet. And ironically, Python is the best language in the world for writing applications, but not the best for writing compilers for itself. Thank you. Yeah, can also ask questions on the social event. I am a bit over time, I'm sorry.
Speaker 2 [30:27]
I'm going to ask one question though, because it's bugging most people in the room.
Speaker 1 [30:31]
the room there's 17 is it is it about astral and what that means about what is
Speaker 2 [30:35]
What is your opinion on the recent acquisition of Astral by OpenAI?
Speaker 1 [30:40]
And ironically, the slide above the community thing was done on the same, I did the slide, and afterwards, like an hour later, a colleague comes to me and tells, Stefan, Astral just merged forces with, yeah, and I was like, cool, that's a perfect timing. I'm quoting Kyle from yesterday. That's a question you better ask Astral itself. I have done some research for that. So it's not the first big tool that got bought by an AI company. Actually, end of the last year, BAN, the Node.js alternative runtime and all-in-one tool from Oven, Oven got also bought by Anthropic itself. I asked some colleagues and looked into it, and the development itself is still very active. The focus is a bit different. You can see that it more fits what an AI company needs and optimizes it more for AI-specific workflows, like small startup time, different response, and less on the general web-based focus. But the number of contributions has increased for Bunn at least. And I hope that it's the same with Astral. Because let's be honest, everyone has asked how they're going to want to do money at some point. So the realistic outcome would have been this company does not exist at some point and we have three tools that are unmaintained. Now we have to set up that there is a big AI company behind it that at least has a very strong interest Interested these tools are kept alive and I also believe these tools are so relevant for the whole Python ecosystem right now That the community would at some point also take them over if absolutely necessary That's my take but happy to discuss with that
Speaker 2 [32:54]
And with that, we'll have to conclude the session. Please feel free to get in touch with Stefan later. So let's join our hands and thank Stefan again for a wonderful talk.