__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__
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!
Most helpful comment
Thanks for the heads up. I'll look into it.