You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
In the following example, you will see that although the protocol is less strict than what's being passed (str), it raises an error that the type is not exactly str | None
Code or Screenshots
fromdataclassesimportdataclassfromtypingimportProtocolclassSampleProtocol(Protocol):
name: str|None@dataclassclassSampleObj:
name: str# more strict than the protocoldefprint_age(obj: SampleProtocol):
ifobj.name:
print(obj.name)
else:
print("No name")
var=SampleObj(name="John")
print_age(var) # Type "str" is not assignable to type "str | None"
print_age will have the following error:
Argument of type "SampleObj" cannot be assigned to parameter "obj" of type "SampleProtocol" in function "print_age"
"SampleObj" is incompatible with protocol "SampleProtocol"
"name" is invariant because it is mutable
"name" is an incompatible type
Type "str" is not assignable to type "str | None"
"str" is not assignable to "None" (reportArgumentType)
I thought maybe this is because the dataclass is mutable, but making it a frozen dataclass does not change anything.
VS Code extension or command-line
Tried this in vscode and the online playground
The text was updated successfully, but these errors were encountered:
Pyright is working correctly here and in accordance with the typing spec, so this isn't a bug.
Your protocol indicates that the type must accept a value of type str | None for the name field. That means someone could attempt to write a None value to this field and still comply with the protocol. However, this would violate the SampleObj type. For example, consider if print_age included the statement obj.name = None.
Mutable attributes are necessarily treated as invariant by a type checker. It sounds like you expect it to be treated as covariant, which would allow for the "less strict" behavior that you're looking for.
There is a draft PEP 767 that allows an attribute for attributes to be marked ReadOnly. Read-only attributes can be safely treated as covariant. This PEP is still in the development phase and hasn't yet been implemented in pyright, but it is something I plan to add soon.
Describe the bug
In the following example, you will see that although the protocol is less strict than what's being passed (
str
), it raises an error that the type is not exactlystr | None
Code or Screenshots
print_age will have the following error:
I thought maybe this is because the dataclass is mutable, but making it a frozen dataclass does not change anything.
VS Code extension or command-line
Tried this in vscode and the online playground
The text was updated successfully, but these errors were encountered: