Comparación de los dos nuevos type checkers de Python basados en Rust: Pyrefly y Ty
(blog.edward-li.com)- Recientemente se presentaron dos type checkers de Python basados en Rust, Pyrefly de Meta y Ty de Astral, que muestran un rendimiento abrumador y un nuevo paradigma de tipado frente a mypy y pyright
- Pyrefly apuesta por una inferencia de tipos agresiva y el código abierto, mientras que Ty introduce el principio de “gradual guarantee” y se enfoca en minimizar la aparición de errores de tipo
- Aunque ambas herramientas están todavía en versiones alfa iniciales, los benchmarks en varios proyectos muestran que Ty registra en promedio una mayor velocidad de ejecución
- En análisis incremental, Pyrefly trabaja a nivel de módulo, mientras que Ty ofrece una incrementalidad más fina a nivel de función, por lo que difieren tanto en usabilidad como en estructura
- Ty presenta un sistema de tipos innovador con intersection types y negation types, además de mensajes de error más intuitivos y claros
Introducción a Pyrefly y Ty
- Pyrefly y Ty son type checkers de Python desarrollados en Rust
- Pyrefly fue desarrollado por Meta (antes Facebook) y reemplaza a Pyre, que estaba basado en OCaml
- Ty fue desarrollado por Astral, conocida por herramientas de Python como uv y ruff
- Ambos proyectos están publicados como open source, pero todavía se encuentran en fase alfa previa al lanzamiento oficial
- Ambos equipos presentaron su visión, objetivos y enfoque en el Typing Summit de PyCon 2025
Similitudes
- Ambos están desarrollados en Rust y soportan análisis incremental (Incremental Checking)
- Utilizan ruff para el parseo del AST del código Python
- También destacan por su buena integración con el entorno de desarrollo, con verificación de tipos por línea de comandos e integración con LSP/IDE
Diferencia 1: velocidad
Benchmark con PyTorch
- Ty es entre 2 y 3 veces más rápido que Pyrefly, y ambos son entre 10 y 20 veces más rápidos que mypy y pyright
- Pyrefly apunta a mejorar el rendimiento 35 veces frente a Pyre y 14 veces frente a mypy/pyright
- Ty fue diseñado con el objetivo de ser entre una y dos órdenes de magnitud más rápido que los type checkers actuales
Benchmark con Django
- Ty es el más rápido, seguido por Pyrefly
- Pyright muestra resultados claramente más lentos
Benchmark en el repositorio de mypy
- Se observan resultados similares: Ty es el más rápido y Pyrefly lo sigue por un margen pequeño
- mypy y pyright registran tiempos de ejecución notablemente más lentos
Diferencia 2: objetivos de tipado
Pyrefly
- Sigue una estrategia de inferir tipos al máximo posible para detectar errores incluso cuando el código no tiene tipos explícitos
- Busca maximizar la estabilidad del código mediante una inferencia de tipos más agresiva
Ty
- Aplica el principio de gradual guarantee
- Está diseñado para que al eliminar tipos explícitos de código que funciona no aparezcan errores de tipo
- No provoca errores aun sin type annotations, y solo exige anotaciones adicionales cuando son necesarias
- Ejemplo: aunque se asigne un valor a un campo sin tipo explícito, no genera error de tipo y lo trata como
Unknown | None, entre otros casos
Diferencia 3: método de análisis incremental
- Pyrefly: vuelve a analizar solo el archivo cambiado (módulo) y sus módulos dependientes (incrementalidad a nivel de módulo)
- Ty: usa el framework Salsa de Rust para una incrementalidad detallada hasta el nivel de función
- El nivel de módulo se considera suficientemente rápido, mientras que el nivel de función puede volver más compleja la base de código (diferencias de estrategia entre ambas herramientas)
Diferencia 4: funciones (sistema de tipos y soporte)
Ventajas de Pyrefly
- Su inferencia implícita de tipos es muy potente
- Incluso sin tipos explícitos, analiza tipos complejos como valores de retorno de funciones, diccionarios y listas para detectar errores
- Está diseñado con foco en problemas complejos de tipado como genéricos, overloads e imports con comodines
- Su precisión en la inferencia de tipos genéricos es superior a la de Ty
Particularidades de Ty
- Gracias a “gradual guarantee”, permite cambios de tipo libremente aun cuando faltan tipos explícitos
- Soporta sistemas de tipos innovadores como intersection types y negation types
- Sus mensajes de error están diseñados para ser muy claros e intuitivos
- Permite asignar libremente distintos tipos en listas y similares, e introduce de forma sistemática el valor de tipo
Unknown
Limitaciones / estado alfa
- Ambos productos están en fase alfa, por lo que parte de la inferencia de tipos o algunas funciones todavía están incompletas
- Por ejemplo, algunos resultados de Ty, como la inferencia de tipos en listas, todavía muestran falta de madurez
Comparación detallada de funciones
Inferencia implícita de tipos
- Pyrefly infiere activamente tipos de retorno y tipos de objetos de colección, y muestra con claridad el revealed type y los errores
- Ty devuelve
Unknowno@Todocuando la inferencia es insuficiente
Genéricos
- Tanto Pyrefly como Ty resuelven bien los problemas comunes de tipos genéricos
- Pyrefly tiene ventaja al interpretar el tipo de instancias creadas sin parámetros de tipo
- Ambos checkers muestran debilidades frente a mypy y pyright en problemas de covarianza/contravarianza (covariance/contravariance)
Mensajes de error
- Ty pone énfasis en mensajes de error concisos y fáciles de leer
- Ofrece mensajes más fáciles de entender de un vistazo que Pyrefly, mypy y pyright
Intersection / negation types
-
Solo Ty soporta intersection types (
&) y negation types (~), lo que le permite manejar operaciones de tipos complejas como las siguientes- Ejemplo: en un tipo
WithX | Other, si existe el atributox, Ty bifurca automáticamente haciaWithX - Ejemplo: si no se trata de una subclase específica, interpreta el tipo como
MyClass & ~MySubclass
- Ejemplo: en un tipo
-
Estas intersection types y negation types son funciones muy avanzadas dentro de la teoría de tipos
Otros ejemplos avanzados
- Ty también puede usarse con su sistema de tipos para operaciones complejas como ecuaciones diofánticas
- Las pruebas están escritas en documentos Markdown (referencia: recursos mdtest de Astral ruff)
Conclusión y perspectivas
- El ecosistema de Python ahora cuenta con type checkers nuevos y abrumadoramente rápidos
- Ty adopta como estrategia principal la estabilidad gradual de tipos, mientras que Pyrefly se enfoca en la inferencia activa de tipos
- Como ambas herramientas todavía están en una etapa temprana, hay mucho margen para que sus funciones converjan o evolucionen
- Se pueden probar en sus sitios oficiales, y también ofrecen plugins para editores principales como VSCode y Cursor
- También se rumorea que Google planea liberar como open source un type checker basado en Go, por lo que se espera que el campo del análisis de tipos en Python se vuelva aún más rico
Uso / referencia
- Pyrefly: pyrefly.org/sandbox
- Ty: play.ty.dev
- Ty de Astral utiliza pruebas basadas en Markdown (para la ruta detallada, consultar mdtest en el repo de ruff)
- También se proporcionan documentación oficial, plugins para editores y comandos de instalación de paquetes
2 comentarios
Parece que
tymarca comounknownsí o sí si la función que usas no tiene tipo de retorno anotado; solo te lo confirma después de guardar.pyreflylo infiere aunque no esté anotado, y también te lo muestra mientras escribes.Comentarios de Hacker News
Un desarrollador de ty expresa su alegría porque ty y pyrefly estén recibiendo cada vez más atención, pero vuelve a enfatizar que ambos proyectos aún no están terminados; también comenta que ha visto ejemplos causados por funciones no implementadas y pide comprensión cuando algo parezca “esto está raro”, ya que podría ser una parte que todavía no ha sido desarrollada; hace falta tener presente que Python es un lenguaje enorme y diverso.
A alguien le encanta el estilo de pruebas en markdown de ty; le parece una idea excelente que las pruebas también funcionen como documentación, y pregunta si este enfoque estuvo inspirado en los ejemplos de código documentados de Rust.
A otro le dio risa que las partes donde se revelan tipos estén marcadas con
@TODO, pero al pensarlo mejor le pareció un recurso bastante ingenioso y útil.Desde la perspectiva de alguien con experiencia en TypeScript, le resultan interesantes los distintos intentos alrededor de la inferencia de tipos, el type narrowing y el hecho de que cada type checker de Python se comporte de manera distinta; sigue haciendo falta un type checker rápido y confiable, pero siente que Python está bastante rezagado en este aspecto; cree que un type checker debería aumentar la productividad y la confiabilidad del código, y apoya este tipo de proyectos.
Desde la mirada de un desarrollador de Rust, surge una pregunta sobre un “lenguaje de scripting para Rust”: si existe alguna comunidad investigando un lenguaje cuya sintaxis combine bien con Rust, que pueda importar tipos de Rust de forma nativa y compile rápido o permita hot reload; también pide opiniones sobre si Python podría cumplir ese rol aunque la sintaxis sea distinta, y adjunta un enlace relacionado: https://news.ycombinator.com/item?id=44050222
Opinión desde una perspectiva externa con poca experiencia en Python: si te interesa el uso de type hints, recomienda revisar este post de Reddit https://www.reddit.com/r/Python/comments/10zdidm/why_type_hinting_sucks/ ; aclara que no hay que tomárselo demasiado en serio, pero enfatiza que, por buenas que sean las herramientas de tipos, primero van las “buenas prácticas”; por ejemplo, para lograr un uso consistente y type checking estricto en codebases grandes como Django o Meta, hay que hacer que los desarrolladores sigan ciertas convenciones recomendadas; señala que Python, como C++, tiene demasiadas funciones y un runtime demasiado permisivo, así que al final conviene usar solo una parte limitada si se quiere mantenerlo manejable, aunque esa parte puede variar según la persona y el objetivo; también lo compara con los casos en que desarrolladores de Rust chocan con mantenedores del kernel de Linux por un sistema de tipos más estricto.
En uno de los comentarios más votados de ese post de Reddit se descarta el tema con un “puedes usar
Any, así que la discusión no tiene sentido”, pero se responde que en casos reales una declaración de tipos más clara puede evitar por adelantado errores ante futuros cambios en funciones de librerías o valores de entrada inesperados; se sostiene con fuerza que el type checking es indispensable para que el código Python sea mantenible y confiable.Conclusión de que, en vez de invertir demasiado tiempo y esfuerzo en el type checking de Python, quizá sea mejor migrar a un lenguaje estático más adecuado y usar Python solo donde haga falta mediante una capa de interop; no siempre es posible, pero existe la preocupación de estar desperdiciando demasiado tiempo tratando de forzar a Python a encajar.
Crítica a funciones poderosas y complejas de Python —por ejemplo meta class, descriptor, uso de
__call__,object.__new__, name mangling yself.__dict__— por meter demasiada “magia” y perjudicar mucho la legibilidad del código; en lo personal, declara que prefiere no usar ese tipo de funciones.Se pregunta de dónde viene esa costumbre de opinar sin usar realmente el lenguaje; comenta que quienes desarrollan en Python lo entienden a fondo a partir del uso real, y le llama la atención que alguien que no lo usa critique el lenguaje basándose en argumentos externos; también señala un ambiente de discusión basado en ejemplos forzados.
Una persona con muchos años usando Python afirma que el mayor error es no usar type hints ni type checkers en absoluto.
A alguien le parece interesante la “garantía gradual” de ty: es decir, que quitar una anotación de tipo no debería producir errores de tipo; le resulta atractivo y cree que es el enfoque más adecuado para Python, donde hay mucho código dinámico.
Recuerda que el tipado gradual permite que haya
any(tipo no determinado) en cualquier parte del código sin ni siquiera generar advertencias, y que eso hacía que incluso el código importante no quedara realmente protegido por una seguridad de tipos completa; dice que esto fue un problema grave en su experiencia con mypy y que hace falta una función para declarar “este archivo se type checkea de forma completamente estática”; en su opinión personal, el tipado “gradual” se acerca más a un anti-pattern, e incluso piensa que el término “soft typing” podría describirlo mejor.Otra postura sostiene que en una codebase existente no hay alternativa real al tipado gradual; según su experiencia agregando type hints con mypy en varios codebases legacy de Python, el “opt-in por módulo” es lo más razonable; si pyrefly no soporta eso, su utilidad práctica sería limitada; aun así, desde el ángulo de la generación de código con llm (modelos de lenguaje de gran escala), sí ve valor en un type checker muy rápido y estricto.
Lo comparan con la adopción inicial de TypeScript, priorizando una incorporación suave en proyectos grandes ya existentes; después se pueden ir activando opciones como
noImplicitAnyostrictpor módulo hasta convertir el entorno en uno con verificación de tipos fuerte.Incluso como programador de Rust, alguien considera que la “garantía gradual” es lo más sensato.
Otra persona dice que el soporte para tipado gradual no le resulta especialmente atractivo; si el sistema de tipos dinámico de Python ya es inestable, entonces la mitad del propósito de agregar anotaciones de tipo es justamente controlar ese mal comportamiento; por eso desea que existan opciones obligatorias como no-implicit-any o modo estricto.
Las herramientas de Astral le han dado energía fresca al ecosistema de Python, pero se plantean dudas sobre su “visión a largo plazo”: ¿se integrarán directamente en Python?, ¿desaparecerán en cinco años?, ¿terminarán en un rug pull basado en suscripciones?
Se especula que, mediante una Business Source License, Astral podría terminar empujando suscripciones empresariales u otros pagos obligatorios para despliegues en producción que usen sus herramientas; los productos actuales no parecen hechos exactamente para eso, pero desde la lógica del venture capital podría ir por un modelo parecido.
Se menciona que en un anuncio oficial Astral dijo explícitamente que venderá diversos servicios sobre sus herramientas; enlace de referencia: https://astral.sh/blog/announcing-astral-the-company-behind-ruff
En realidad, se advierte que esta preocupación no aplica solo a Astral sino a todos los proyectos, y especialmente que las herramientas de Facebook corren un alto riesgo de quedar abandonadas con el tiempo; al final, el consejo es que los usuarios siempre deben asumir ese riesgo por su cuenta.
Se cita la opinión de un usuario de Reddit según la cual el modelo básico del VC consiste en esperar ser adquiridos por una FAANG o crecer de forma agresiva para buscar un “acqui-hire”; Astral también podría terminar en un escenario de adquisición y absorción de talento.
Circulan rumores de que Astral está preparando herramientas exclusivas para grandes empresas, por ejemplo un private package registry hospedado.
A partir del ejemplo
my_list = [1, 2, 3], se cuestiona que mypy, pyrefly y pyright considerenmy_list.append("foo")como error de tipo, mientras que ty lo permite sin ninguna indicación adicional; se argumenta que en el trabajo real lo habitual es usar listas de un solo tipo, así que un type checker debería asumir eso; se critica con fuerza que, solo porque Python lo permita, la validación de tipos no debería volverse más laxa, y se pregunta si no será una política optimizada para código de principiantes.Un desarrollador de ty aclara que “la inferencia de tipos para literales de lista todavía no está terminada”; por ahora simplemente usa
list[Unknown], yUnknownes un tipo gradual parecido a Any, así queappendacepta de todo; hay planes para una inferencia más precisa en el futuro, y adjunta un issue relacionado: https://github.com/astral-sh/ty/issues/168Otra opinión dice que no es tanto una optimización para principiantes como una necesidad para compatibilidad con código legacy; si quieres introducir un type checker en mucho código no tipado, el costo es menor si el código existente puede seguir funcionando casi igual.
Se rebate que “ignorar lo que Python permite y construir tooling basado en opiniones personales no es una postura convincente”.
También se señala como problema del enfoque de pyrefly que “es difícil adoptarlo de golpe en codebases grandes sin tipos”; como hay que ir corrigiendo el código manualmente, si no existe consenso dentro de la organización esa tarea se vuelve complicada; en lugares como Meta, donde puede imponerse internamente, funciona, pero pensando en una adopción gradual el enfoque más permisivo de ty parece más realista; aun así, la persona dice que en lo personal prefiere una herramienta que advierta sobre tipos mixed.
Otra opinión sostiene que “si es código Python ejecutable, entonces no debería dar error de tipo salvo que se restrinja explícitamente el tipo”; si se quiere un subconjunto estático más estricto, la solución sería agregar anotaciones de tipo de forma explícita.
Según alguien con experiencia, el enfoque de Pyrefly apuesta más fuerte por la inferencia de tipos y en la práctica requiere muchas menos anotaciones para obtener código seguro en codebases grandes; aunque la adopción inicial sea difícil, a largo plazo sería más eficiente; dice además que ty está básicamente en un estado equivalente a tener desactivada la opción noImplicitAny.
Se expresa el deseo de contar con un type checker con soporte serio para notebooks (live coding), para atrapar errores de antemano con análisis estático antes de ejecutar celdas largas, lo que sería una enorme mejora de eficiencia.
Se pregunta por la experiencia de usar notebooks de Jupyter en VSCode, señalando que aplicar type checkers como pylance puede llegar a estorbar en código experimental.
Se recomienda la experiencia del Language Server de VSCode, que ofrece feedback inmediato durante live coding y resuelve la necesidad de integración con notebooks y type checking interactivo en vivo.
A alguien el diseño de Pyrefly le parece más razonable porque se asemeja al enfoque de inferencia de tipos de TypeScript, y valora como ideal una adopción gradual a nivel de módulo; llevarlo hasta el nivel de función le parece demasiado granular e innecesario, y además considera que, en términos de rendimiento, el nivel de módulo es suficiente.
Otra postura dice que, incluso en proyectos con mucha dinámica, seguiría prefiriendo una inferencia de tipos más fuerte como la de Pyrefly, aun si eso trae incomodidades.
Actualmente alguien usa basedpyright en IDE y CI, y en general está satisfecho con su estabilidad; no le gusta mypy porque a veces falla incluso en tareas de tipos simples.