Mypy: "Expected TypedDict key to be string literal" false positive?

Created on 16 Oct 2017  路  3Comments  路  Source: python/mypy

Shouldn't something like this work?

from mypy_extensions import TypedDict

Details = TypedDict('Details', {'first_name': str, 'last_name': str})
DetailsSubset = TypedDict('DetailsSubset', {'first_name': str, 'last_name': str}, total=False)
defaults = {'first_name': 'John', 'last_name': 'Luther'}  # type: Details


def generate(data: DetailsSubset) -> Details:
    return {**defaults, **data}

I'm getting:

% mypy code.py 
code.py: error: Expected TypedDict key to be string literal

Oh, and the error message is missing the line number, that could be handy to have.

I'm using mypy 0.530 and Python 3.6.2.

bug priority-1-normal topic-typed-dict topic-usability

Most helpful comment

Hm, the missing line number is a bug. The error is clearly about the final line of your example.

Unfortunately mypy isn't smart enough to understand that in this particular case the result will have exactly the desired set of keys. It basically gives up as soon as it sees {**expr}. Maybe we could teach it to calculate the minimal and maximal sets of keys for such usage (if **expr references a TypedDict) and give better diagnostics based on that.

I believe there are many other ways of constructing a TypedDict that won't be accepted; I think the best way is to just use a cast or put # type: ignore on it.

All 3 comments

Hm, the missing line number is a bug. The error is clearly about the final line of your example.

Unfortunately mypy isn't smart enough to understand that in this particular case the result will have exactly the desired set of keys. It basically gives up as soon as it sees {**expr}. Maybe we could teach it to calculate the minimal and maximal sets of keys for such usage (if **expr references a TypedDict) and give better diagnostics based on that.

I believe there are many other ways of constructing a TypedDict that won't be accepted; I think the best way is to just use a cast or put # type: ignore on it.

The missing line number should be easy to fix, but the {**expr} type detection might be harder.

This is still an issue in 0.782. Has anything changed since 0.530 that could make the type detection for this case feasible? I.e. the discussion in #4441 seems relevant.

My current workaround is to use cast. A bit better than # type: ignore.

Was this page helpful?
0 / 5 - 0 ratings