Repository navigation
No type inference for dicts in union #6463
Description
Activity
I’m sure the cause is the union, not the tuple.
- changed the title
[-]No type inference for dicts in tuples[/-][+]No type inference for dicts in union[/+]on Feb 22, 2019 @gvanrossum thanks, you're right - corrected the issue title and the sample code
- addedbugmypy got something wrongmypy got something wrongfalse-positivemypy gave an error on correct codemypy gave an error on correct code
on Feb 22, 2019 @ikonst you could try this to have a workaround, though the semantics has changed
def bar() -> Dict[Union[str, int], Any]: return {}This may be a duplicate of #2164
@oraluben - the actual code is more complex:
from typing import * from flask import Response JsonDict = Dict[str, Any] _FlaskResponse = Union[ str, bytes, Callable, Response, ] _FlaskRestfulResponse = Union[ JsonDict, _FlaskResponse, ] FlaskRestfulMethodReturnType = Union[ _FlaskRestfulResponse, Tuple[Optional[_FlaskRestfulResponse], int], # (response, status_code) Tuple[Optional[_FlaskRestfulResponse], int, Dict[str, str]], # (response, status_code, headers) Tuple[Optional[_FlaskRestfulResponse], Dict[str, str]], # (response, headers) ]
and then this works:
class MyResource(Resource): def get() -> FlaskRestfulMethodReturnType: return {}
and this works:
class MyResource(Resource): def get() -> FlaskRestfulMethodReturnType: return {"foo": "bar"}, 200
but this doesn't:
class MyResource(Resource): def get() -> FlaskRestfulMethodReturnType: return {}, 200
This happens with other invariant containers as well, such as lists. I just encountered an instance where mypy couldn't infer the type of a
{}function argument when callingstring.Template.substitute, since the type of the argument in the signature is a union.This also happens with dicts inside a tuple:
from typing import Dict, Tuple, Union T = Dict[str, str] U = Tuple[T] def f() -> U: return {}, def g() -> Union[U, U]: return {},
10: error: Incompatible return value type (got "Tuple[Dict[<nothing>, <nothing>]]", expected "Union[Tuple[Dict[str, str]], Tuple[Dict[str, str]]]")You can work around this issue with:
from typing import * def get_empty_list_str() -> List[str]: return [] def get_empty_list_int() -> List[int]: return [] foo: Union[List[str], List[int]] = get_empty_list_str() # fine bar: Union[List[str], List[int]] = get_empty_list_int() # fine baz: Union[List[str], List[int]] = [] # errori.e., create a function to create an empty container with a defined type.
You can solve the original issue like this (note, it doesn't matter what the type of your constructor function is as long as it is one of the Union types):from typing import * def foo() -> Dict[str, Any]: return {} def bar() -> Union[Dict[str, Any], Dict[int, Any]]: return foo()- added a commit that references this issue
on Oct 7, 2021 This false-positive is also there with unions of lists when assigning an empty list (e.g.
var: Union[list[int], list[str]] = [].The issue is a few years old at this point but the case is not obscure enough that it would only occur in very few codebases. What's the status on this?
Reacted by Govind RaiReacted by Kelly Brazil, nss-csis, Wannes Rombouts, James Lamb and Govind RaiThanks @JosuaKrause for the work around. This actually can be done very concisely in newer python versions by using
list[str](),dict[str, int](), etc. as constructors for a typed empty iterators:foo: list[str] | list[int] = list[str]() # fine bar: list[str] | list[int] = list[int]() # fine baz: list[str] | list[int] = [] # error
Reacted by Zev Isert- added a commit that references this issue
on Sep 26, 2023
In
foo,{}is inferred asDict[str, Any].In
bar, I get: