Getting this typing error:
error: Incompatible types in assignment (expression has type "object", variable has type "A | B") [assignment]
With this code:
from dataclasses import dataclass
from typing import TypeVar, Mapping, reveal_type
@dataclass
class A:
foo: str = "a"
@dataclass
class B:
bar: str = "b"
lookup_table: Mapping[str, type[A] | type[B]] = {
"a": A,
"b": B
}
reveal_type(lookup_table) # note: Revealed type is "typing.Mapping[builtins.str, Union[type[simple.A], type[simple.B]]]"
T = TypeVar("T")
def load(lookup_table: Mapping[str, type[T]], lookup_key:str) -> T:
con: type[T] = lookup_table[lookup_key]
instance: T = con()
return instance
example_a: A | B = load(lookup_table, "a") # error: Incompatible types in assignment (expression has type "object", variable has type "A | B")
print(example_a)
Edit: Logged a mypy bug here: https://github.com/python/mypy/issues/18265
This is a mypy bug present in 1.13.0 and below (previously reported here and by OP here). pyright and basedmypy both accept the given snippet.
mypy stores type[A | B] types as a union of types internally (type[A] | type[B]). This is usually convenient, but causes troubles when solving type[T] <: type[A] | type[B] for T, because most types aren't "distributive" (P[A, B] is not equivalent to P[A] | P[B]), and type special case isn't taken into account yet.
General solver produces meet(A, B) in such case by solving
type[T] <: type[A] => T <: A |
| => T <: meet(A, B)
type[T] <: type[B] => T <: B |
When A and B have no explicit parent in common, the closest supertype is object. To understand the logic behind that, consider similar equations: x < 2 && x < 3 => x < min(2, 3), and intersection/meet is for types what min operation is for numbers (and union/join is similar to max).
I submitted a PR to special-case this behaviour, so things may change in a future mypy release.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With