Precise typing for TypedDict wrappers
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Python
- Estrellas
- 20.6k
- Forks
- 3.3k
- Métricas de merge de PR
- Métricas de PR pendientes
Descripción
Bug or feature request: feature request (I think)
I tried to use TypedDict for my codebase and ran into some issues. Consider the following code snippet:
from typing import Any, Union, Optional
from typing_extensions import Literal
from mypy_extensions import TypedDict
class Test(TypedDict):
a: str
b: int
c: int
TestKeys = Literal["a", "b", "c"] # QUESTION: is there a Test.KEYS or something equivalent?
TestValue = Union[str, int] # QUESTION: is there a Test.VALUE_TYPES or something equivalent?
class Foo:
def __init__(self):
self._foo: Optional[Test] = None
def _set(self) -> None:
self._foo = {"a": "a", "b": 0, "c": 1}
def __getitem__(self, key: TestKeys) -> Any:
self._set()
assert self._foo is not None
return self._foo[key]
def a(self) -> str:
return self["a"]
def b(self) -> int:
return self["b"]
class Bar:
def __init__(self):
self._bar: Optional[Test] = None
def _set(self) -> None:
self._bar = {"a": "a", "b": 0, "c": 1}
def __getitem__(self, key: TestKeys) -> TestValue:
self._set()
assert self._bar is not None
return self._bar[key]
def a(self) -> str:
return self["a"] # WRONG: Incompatible return value type (got "Union[str, int]", expected "str")
def b(self) -> int:
return self["b"] # WRONG: Incompatible return value type (got "Union[str, int]", expected "int")
a = Foo().a()
a.find("a")
b = Foo().b()
b.find("a") # CORRECT: "int" has no attribute "find"
c = Foo()["a"]
c.find("a")
d = Foo()["b"]
d.find("a") # MISSING: no error reported here (if self._foo is not lazily initialized the error gets correctly reported)
e = Bar().a()
e.find("a")
f = Bar().b()
f.find("a") # CORRECT: "int" has no attribute "find"
g = Bar()["a"]
g.find("a") # WRONG: Item "int" of "Union[str, int]" has no attribute "find"
h = Bar()["b"]
h.find("a") # WRONG: Item "int" of "Union[str, int]" has no attribute "find" (should be "int" has no attribute "find")
(Python 3.8.0, mypy==0.740, mypy-extensions==0.4.3)
I'm not sure what the correct return type signature for a wrapping __getitem__ would be. Both Any and Union seem to erase the actual type coming from the TypedDict and lead to incorrect results. Is there currently a way to achieve the desired behavior here? Also, is there a way to specify Literals for the keys without manually copying them?
Something like
KT = TypeVar("KT", bound=TestKeys) # or better Test.KEYS
def __getitem__(self, key: KT) -> Test[KT]:
...
would be cool if it worked.
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Usa el ejemplo del wrapper TypedDict en el issue como reproducción y céntrate en los tipos de retorno genéricos de getitem, los literales de clave y la inicialización diferida. Compara los diagnósticos reportados y esperados para los ejemplos con a, b e indexed-access; se considera terminado cuando la inferencia de valores es precisa sin duplicar manualmente las claves ni los tipos de TypedDict.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- python
- Área
- devtools
- Tipo de issue
- Nueva funcionalidad
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Estado de actividad
- Estancado
- Claridad
- Bastante claro
- Aptitud para principiantes
- 35/100