Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dictionary infering value type #7244

Closed
RonNabuurs opened this issue Jul 19, 2019 · 5 comments
Closed

Dictionary infering value type #7244

RonNabuurs opened this issue Jul 19, 2019 · 5 comments

Comments

@RonNabuurs
Copy link

RonNabuurs commented Jul 19, 2019

Is it possible for mypy to infer the value of an dictionary?

I've got a problem with value types not being recognized correctly.

Example:

from typing import Dict, Union

D = Union[Dict[int, str], Dict[int, int], Dict[int, bool], Dict[int, float]]

d: D = {
    0: 1,
    1: 2
}

reveal_type(d[0])
d[0] = 123 # This generates an error, this should not error in my opinion

d2: D ={
    0: 'str1',
    1: 'str2'
}

reveal_type(d2[0])
d2[0] = 'newstr' # This generates an error, this should not error in my opinion

D2 = Dict[int, Union[str, int, bool, float]]

d3: D2 = {
    0: 1,
    1: 2
}

reveal_type(d3[0])
d3[0] = 1
d3[0] = 'asdf' # This is ok, but I don't want to be able to change the type of a value like this

mypy output

test.py:10: note: Revealed type is 'Union[builtins.str*, builtins.float*]'
test.py:11: error: Incompatible types in assignment (expression has type "int", target has type "str")
test.py:11: error: Incompatible types in assignment (expression has type "int", target has type "bool")
test.py:18: note: Revealed type is 'Union[builtins.str*, builtins.float*]'
test.py:19: error: Incompatible types in assignment (expression has type "str", target has type "bool")
test.py:28: note: Revealed type is 'Union[builtins.str, builtins.int, builtins.bool, builtins.float]'

The revealed type on line 10 and 18 also don't seem to be right.

@JukkaL
Copy link
Collaborator

JukkaL commented Jul 19, 2019

The revealed types on linen 10 and 18 are simplified union types. Mypy considers bool compatible with int, and since int can be promoted to float, Union[bool, int float] is simplified to float (but we may want to change this at least in some contexts, since it's confusing -- see #6168).

Do the error messages make sense assuming unions are simplified, or there another issue with the errors mypy is reporting?

@RonNabuurs
Copy link
Author

That makes sense too me. Its indeed a bit confusing.

I see I made a typo though, I meant that the error shouldn't happen. At least thats what I thing. The error on line 11 and on line 19 are incorrect.

@JukkaL
Copy link
Collaborator

JukkaL commented Jul 19, 2019

Errors on lines 11 and 19 are as expected. You can avoid the errors by having a separate variable type declaration and assignment. This causes mypy to narrow the type down. This doesn't happen if you declare the type and assign a value in the same statement. Example:

from typing import Dict, Union

D = Union[Dict[int, str], Dict[int, int], Dict[int, bool], Dict[int, float]]

d: D  # Note separate declaration
d = {
    0: 1,
    1: 2
}

reveal_type(d[0])
d[0] = 123 # No error

I think that this might not be properly documented, though.

@RonNabuurs
Copy link
Author

I've tried with the seperate declaration and it seems to work, thanks!
Indeed this might not be properly documented, because I haven't found it.

@JukkaL
Copy link
Collaborator

JukkaL commented Jul 22, 2019

I added an issue about documenting this #7252.

@JukkaL JukkaL closed this as completed Jul 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants