5 ms·
Funny, I ran into the same pattern just a few months ago! In practice, I found it difficult for coworkers to read and understand so I dropped the idea. Anothe
by sdeframond 5mo ago
Funny, I ran into the same pattern just a few months ago!
In practice, I found it difficult for coworkers to read and understand so I dropped the idea.
Another limitation I found is that it breaks down when you start using inheritance. For example:
```
class _A: pass
A = NewType("A", _A)
class _B(_A): pass
B = NewType("B", _B)
def foo(a: A) -> None:
pass
b = B(_B())
foo(b) # Mypy is not happy: Argument 1 to "foo" has incompatible type "B"; expected "A"
foo(A(b)) # Mypy is OK
```
- simonw 5mo ago(On Hacker News you can do code blocks by indenting each line with two spaces.)
- sdeframond 5mo agoAaah nice! Thank you!
- whilenot-dev 5mo agoJust use a generic and make it bound to (A, B): from typing import * class _A: pass class _B(_A): pass A = NewType("A", _A) B = NewType("B", _B) def foo[T: (A, B)](val: T) -> T: return val a = A(_A()) b = B(_B()) _a = foo(a) _b = foo(b) reveal_type(_a) reveal_type(_b) Playground here: https://mypy-play.net/?mypy=latest&python=3.12&gist=3657336346fd926ac50cccccfc09696a https://mypy-play.net/?mypy=latest&python=3.12&gist=36573363...
- sanderjd 5mo agoThis does seem like an abstraction leak though.
- whilenot-dev 5mo agoThe abstraction gets leaky once you expect the distinct NewTypes to adhere to the original inheritance property. I think that's a wrong assumption from the get-go. OP could just do: def foo(val: _A) -> None: pass ...and it'll accept both NewTypes just fine. I guess it depends on whether foo is designed to be public or private.
- sdeframond 5mo agoThis works but it does not let other modules define such methods.