Live data from Hacker News

Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

blog.edward-li.com

21–30 of 166 posts

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#21

> my_list = [1, 2, 3] > pyrefly, mypy, and pyright all assume that my_list.append("foo") is a typing error, even though it is technically allowed (Python collections can have multiple types of objects!) > If this is the intended behavior, ty is the only checker that implicitly allows this without requiring additional explicit typing on my_list. EDIT: I didn't intend my comment to be this sharp, I am actually rooting…

I don't think it's optimizing for beginner-level code, I think it's optimizing for legacy code. Introducing a type checker to a large existing untyped codebase is a big lift, but becomes less of one if almost all existing code is accepted.

Well then support an option to enable that kind behaviour? Make it an explicit decision by the devs. I think running in a type error and then adding an exception to your config is safer than silently pass and only learn about the mixed types in a production bug

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#22

> my_list = [1, 2, 3] > pyrefly, mypy, and pyright all assume that my_list.append("foo") is a typing error, even though it is technically allowed (Python collections can have multiple types of objects!) > If this is the intended behavior, ty is the only checker that implicitly allows this without requiring additional explicit typing on my_list. EDIT: I didn't intend my comment to be this sharp, I am actually rooting…

I don't know. I would argue that since type checking in python is optional, the type checkers shouldn't care unless the programmer cares. A more interesting case would be my_list.append(2.45) or my_list.append(Decimal("2.0")). Those cases would be "numbers" not just "ints".

In the real world, a row of CSV data is not type checked -- and the world hasn't pushed the spreadsheet industry to adopt typed CSV data.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#23

> my_list = [1, 2, 3] > pyrefly, mypy, and pyright all assume that my_list.append("foo") is a typing error, even though it is technically allowed (Python collections can have multiple types of objects!) > If this is the intended behavior, ty is the only checker that implicitly allows this without requiring additional explicit typing on my_list. EDIT: I didn't intend my comment to be this sharp, I am actually rooting…

It depends on what happens with the list after that. Are there int specific operations applied or it is just printed? What if it is fed into objects with a str attribute where the ints could be cast to str?

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#24

> my_list = [1, 2, 3] > pyrefly, mypy, and pyright all assume that my_list.append("foo") is a typing error, even though it is technically allowed (Python collections can have multiple types of objects!) > If this is the intended behavior, ty is the only checker that implicitly allows this without requiring additional explicit typing on my_list. EDIT: I didn't intend my comment to be this sharp, I am actually rooting…

> I am strongly against ty behaviour here.

[ty developer here]

Please note that ty is not complete!

In this particular example, we are tripped up because ty does not do anything clever to infer the type of a list literal. We just infer `list[Unknown]` as a placeholder, regardless of what elements are present. `Unknown` is a gradual type (just like `Any`), and so the `append` call succeeds because every type is assignable to `Unknown`.

We do have plans for inferring a more precise type of the list. It will be more complex than you might anticipate, since it will require "bidirectional" typing to take into account what you're doing with the list in the surrounding context. We have a tracking issue for that here: https://github.com/astral-sh/ty/issues/168

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#25

> my_list = [1, 2, 3] > pyrefly, mypy, and pyright all assume that my_list.append("foo") is a typing error, even though it is technically allowed (Python collections can have multiple types of objects!) > If this is the intended behavior, ty is the only checker that implicitly allows this without requiring additional explicit typing on my_list. EDIT: I didn't intend my comment to be this sharp, I am actually rooting…

> and it is critical that the typechecker assumes this Why is it critical though? If having a `list[int]` was a requirement I would expect a type error where that's explicit.

Because to me this seems like a fantastic example of a highly possible mistake that a typechecker _should_ catch. Without defined types in this situation a couple of things could happen: 1) it gets printed or passed to some other Any method and the typechecker never yells at you and it crashes in production 2) the typechecker catches the error somewhere long down the line and you have to backtrack to find where you might be appending a str to a list[int].

Instead it could mark it as an error (as all the other checkers do), and if that's what the user really intended they can declare the type as list[str | int] and everything down the line is checked correctly.

So in short, this seems like a great place to start pushing the user towards actually (gradually) typing their code, not just pushing likely bugs under the rug.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#26
post #4

I hope some typechecker starts doing serious supported notebook integration. And integration for live coding, not just a batch script to statically check your notebook. Finding errors with typing before running a 1-60 minute cell is a huge win.

Do you use Jupyter notebooks in VSCode? It uses the same pylance as regular python files, which actually gets annoying when I want to write throwaway code.

Anyone reading this, if you're like me and prefer the open source version of VSCode where Microsoft disables Pylance, I'd encourage you to try BasedPyright instead.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#27
[ty developer here]

We are happy with the attention that ty is starting to receive, but it's important to call out that both ty and pyrefly are still incomplete! (OP mentions this, but it's worth emphasizing again here.)

There are definitely examples cropping up that hit features that are not yet implemented. So when you encounter something where you think what we're doing is daft, please recognize that we might have just not gotten around to that yet. Python is a big language!

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#28
I’ve built a few typecheckers (in different languages) that hew closer to Pyrefly’s behaviour than Ty’s behaviour.

If you have a large codebase that you want to be typesafe, Pyrefly’s approach means writing far fewer type annotations overall, even if the initial lift is much steeper.

Ty effectively has noImplicitAny set to false.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#29
post #8

Earlier quoted context omitted.

Gradual typing means that an implicit "any" (unknown type) anywhere in your code base is not an error or even a warning. Even in critical code you thought was fully typed. Where you mistakenly introduce a type bug and due to some syntax or inference limits the type checker unexpectedly loses the plot and tells you confidently "no problems in this file!" I get where they're coming from, but the endgame was a huge issu…

Responding to your gradual typing anti-pattern bit: Agree that dynamic language behaviors can be extreme but it’s also easy to get into crazy type land. Putting aside a discussion of type systems, teams can always add runtime checks like pydantic to ensure your types match reality. Sorbet (Ruby typechecker) does this where it introduces a runtime checks on signatures. Similarly in ts, we have zod.

> teams can always add runtime checks like pydantic to ensure your types match reality.

That's the problem with bugs though, there's always something that could have been done to avoid it =)

Pydantic works great in specific places, like validating user supplied data, but runtime checks as a replacement for static type checkers are not really feasible.

Every caller would need to check that the function is being called correctly (number and position of args, kwarg names, etc) and every callee would need to manually validate that each arg passed matches some expected type.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#30

> my_list = [1, 2, 3] > pyrefly, mypy, and pyright all assume that my_list.append("foo") is a typing error, even though it is technically allowed (Python collections can have multiple types of objects!) > If this is the intended behavior, ty is the only checker that implicitly allows this without requiring additional explicit typing on my_list. EDIT: I didn't intend my comment to be this sharp, I am actually rooting…

> I am strongly against ty behaviour here. [ty developer here] Please note that ty is not complete! In this particular example, we are tripped up because ty does not do anything clever to infer the type of a list literal. We just infer `list[Unknown]` as a placeholder, regardless of what elements are present. `Unknown` is a gradual type (just like `Any`), and so the `append` call succeeds because every type is assign…

I hope I didn't come off as angry or anything, I was just very surprised by the behaviour :)

I am talking from some experience as I had to convert circa 40k lines of untyped code (dicts passed around etc) to fully typed. IIRC this behaviour would have masked a lot of bugs in my situation. (I relied on mypy at first, but migrated to pyright about 1/4 in).

But otherwise it's good to hear that this is still in progress and I wish the project the best of luck.

Post reply on HN