Pyright: Support for typing_extension TypedDict

Created on 7 May 2019  路  12Comments  路  Source: microsoft/pyright

__I'm not sure if this is a new feature request or wrong usage/implementation__

3th party package returns object with __getItem__ implementation:

# object structure: {"ok": True, "error":"", result: "..."}
# usage:
if response['ok']:
    do_something()...

I'm writing the following type stub for the package and having difficulties to get the correct property type from __getItem__

from typing import Mapping

class ServerResponse(Mapping):
    ok: bool
    error: str
    result: str

Type of response['ok'] is __Any__ where it should be inferred from the class property type as __bool__

addressed in next version enhancement request

Most helpful comment

Thanks for the heads up. I'll look into it.

All 12 comments

If an object implements __getitem__ but returns different types based on the parameter, there's no correct way to annotate the type.

You might be able model it in the stub file as a data class or a NamedTuple. Pyright supports both of these constructs.

Seems like I can use NamedTuple to model the response type (since data class doesn't support __getitem__).

but the property type still inferred as Unknown:

Stub file:

from typing import NamedTuple
SlackClientActions = TypeVar('T', 'files.upload', 'chat.postMessage')

class ServerResponse(NamedTuple):
    ok: bool
    error: str
    result: str

class SlackClient(object):
    def api_call(self, action: SlackClientActions, channels: str, title: str, as_user: bool, content: str, initial_comment: str) -> ServerResponse: ...

Usage:

result = client.api_call('files.upload', ...)
result['ok'] # - type is Unknown, should be bool

see also typedDict from mypy_extensions

That's because you're using a string as an index. Is there a reason you can't use result.ok to access the object member?

In the general case where a string expression is used as a index (e.g. result['val_{}'.format(index)'], there's no way for a static type checker to determine the type. I could add a special case for expressions that consist of a single static string. I already have similar logic in place for a single static number used to index into a NamedTuple (e.g. result[3]).

Thanks for pointing out typedDict. I wasn't aware of that.

The returned object is returned from json.loads, which can be accessed only as result['ok']

I see. Yeah, then a TypedDict would be more appropriate in this case. I'll work on implementing support for TypedDict.

I investigated this further. Turns out that there is no support for TypedDict in typing_extension. It's currently found only in mypy_extensions. I don't want to take a dependency on that.

There is an official spec for TypedDict as a proposed addition to Python 3.8.

TypedDict is now supported in typing_extension: https://github.com/python/typing/commit/6e6e4dd6c0b33087a39891ceb142c269f05e2be9#diff-a705b8de8437703698ee3f286d3005a4

Any plans to support it in pyright in the near future?

Thanks for the heads up. I'll look into it.

Support for TypedDict will be included in the next release of pyright.

This is now implemented in 1.0.65, which I just published. I tried to implement all aspects of PEP 589, including the class-based representation of TypedDict as well as the alternate (backward-compatible) syntax that mirrors NamedTuple declarations. Let me know if you run into any problems. Thanks for your patience on this one. I was waiting for the support to make it into the official typeshed typing_extension.pyi file.

Amazing, thanks!

Was this page helpful?
0 / 5 - 0 ratings