-
I am trying to create a type hint that works similar for from typing import Sequence
def as_list(arr: list[str|int]): ...
def as_seq(arr: Sequence[str|int]): ...
my_arr = ["A", "B"]
as_seq(my_arr) # GOOD
as_list(my_arr) # BAD My attempts are shown below, but I have run into an issue. I thought maybe if I switched to mapping, I could get the type hint correct, but it seems that doesn't matter in this case. I then tried manually specifying each of the possible types the dict could be (suboptimal, I know), which resulted in a weird error when I tried to pass the parameter to Any thoughts / suggestions on the correct way to do this are welcome. Using Python 3.12.4 on Windows 11. Codefrom typing import Literal, Mapping
KEYS = Literal["A", "B"]
# These two don't work, which doesn't really surprise me
def dict_key_union(d: dict[KEYS | int, int]):
return dict(d)
def mapping_key_union(d: Mapping[KEYS | int, int]):
return dict(d)
# I tried manually specifying the different types in a union (not ideal), but this causes a weird issue when passing to `dict()`
def dict_union(d: dict[KEYS, int] | dict[int, int] | dict[KEYS | int, int]):
return dict(d)
# ^^^^^^^
# No overloads for "__init__" match the provided argumentsPylancereportCallIssue
# builtins.pyi(1081, 9): Overload 8 is the closest match
# Argument of type "dict[KEYS, int]" cannot be assigned to parameter "map" of type
# "SupportsKeysAndGetItem[_KT@dict, _VT@dict]" in function "__init__"
# "dict[KEYS, int]" is incompatible with protocol "SupportsKeysAndGetItem[_KT@dict, _VT@dict]"
# "__getitem__" is an incompatible type
# Type "(key: KEYS, /) -> int" is incompatible with type "(key: _KT@SupportsKeysAndGetItem, /) -> _VT_co@SupportsKeysAndGetItem"
# Parameter 1: type "_KT@SupportsKeysAndGetItem" is incompatible with type
# "KEYS"PylancereportArgumentType
#
# Argument of type "dict[KEYS, int] | dict[int, int] | dict[KEYS | int, int]" cannot
# be assigned to parameter "iterable" of type "Iterable[list[bytes]]" in function "__init__"
# Type "dict[KEYS, int] | dict[int, int] | dict[KEYS | int, int]" is incompatible with type "Iterable[list[bytes]]"
# "dict[KEYS, int]" is incompatible with "Iterable[list[bytes]]"
# Type parameter "_T_co@Iterable" is covariant, but "KEYS" is not a subtype of "list[bytes]"
# Type "KEYS" is incompatible with type "list[bytes]"
# "Literal['A']" is incompatible with "list[bytes]"PylancereportArgumentType
# (parameter) d: dict[KEYS, int] | dict[int, int] | dict[KEYS | int, int]
def mapping_union(d: Mapping[KEYS, int] | Mapping[int, int]):
return dict(d)
# Usage
my_dict: dict[KEYS, int] = {"A": 1, "B": 2}
dict_key_union(my_dict) # <-- What I actually want
# ^^^^^^^
# Argument of type "dict[KEYS, int]" cannot be assigned to parameter "d" of type
# "dict[KEYS | int, int]" in function "dict_key_union"
# "dict[KEYS, int]" is incompatible with "dict[KEYS | int, int]"
# Type parameter "_KT@dict" is invariant, but "KEYS" is not the same as
# "KEYS | int"PylancereportArgumentType
dict_union(my_dict) # <-- I will settle for this, but it doesn't work internally Possible bugIf this is indeed a bug, I can create a new issue for it. The following snippet can easily recreate the issue: def foo(d: dict[str, int] | dict[int, int]):
return dict(d) Logs of potential relevance
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
_KT = TypeVar("_KT") # Key type.
_VT_co = TypeVar("_VT_co", covariant=True) # Value type covariant containers.
class Mapping(Collection[_KT], Generic[_KT, _VT_co]): ... If I understand your constraints correctly, here's a solution: def dict_key_union(d: dict[KEYS, int]) -> dict[KEYS | int, int]:
return dict(**d)
my_dict: dict[KEYS, int] = {"A": 1, "B": 2}
dict_key_union(my_dict) |
Beta Was this translation helpful? Give feedback.
Thanks for the explanation about the keys.
My actual desired function signature looks like:
Because the dictionary keys can be a type other than
str
(i.e.,int
), I can't simply splat them withdict(**d)
.However, that made me realize that I can stop overcomplicating my life and just do:
With that being said, does the dict union type hint error I noted seem like a bug?