How to forward annotation of __init__ of a dataclass? #3858
-
|
I have a complex dataclass: @dataclasses.dataclass
class ComponentBaseProps(BasicProps):
flex: Union[int, str, Undefined] = undefined
align_self: Union[str, Undefined] = undefined
flex_grow: Union[str, Undefined] = undefined
flex_shrink: Union[str, Undefined] = undefined
flex_basis: Union[str, Undefined] = undefined
...now I want to use annotation of that dataclass in a function: class Component(Generic[T]):
def __init__(self,
prop_cls: Type[T]) -> None:
self.__props = prop_cls()
self.__prop_cls = prop_cls
def prop(self, ANNOTATION_OF_ComponentBaseProps_INIT):
...The only solution I found is treat ComponentBaseProps as a callable: def init_anno_fwd(this: Callable[P, T2]) -> Callable[[Callable], Callable[P, T2]]:
def decorator(real_function: Callable) -> Callable[P, T2]:
def new_function(*args: P.args, **kwargs: P.kwargs) -> T2:
return real_function(*args, **kwargs)
return new_function
return decorator
class Component(Generic[T]):
def __init__(self,
prop_cls: Type[T]) -> None:
self.__props = prop_cls()
self.__prop_cls = prop_cls
@property
def prop(self) -> Type[T]:
@init_anno_fwd(self.__prop_cls)
def wrapper(**kwargs):
for k, v in kwargs.items():
setattr(self.__props, k, v)
return self
return wrapper # type: ignoreThis works in pylance. Questions:
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
|
Yes, it is valid to treat a type as a callable. The callable signature is derived from the constructor of the class (either I don't see a better way of doing this. The challenge is that your code assumes that the constructor accepts a bunch of parameters but can also be called with no arguments (because all of the parameters have defaults). There's no way to express that constraint in the type system, so the type checker doesn't know that you're making this assumption. |
Beta Was this translation helpful? Give feedback.
Yes, it is valid to treat a type as a callable. The callable signature is derived from the constructor of the class (either
__new__or__init__or a combination of both).I don't see a better way of doing this. The challenge is that your code assumes that the constructor accepts a bunch of parameters but can also be called with no arguments (because all of the parameters have defaults). There's no way to express that constraint in the type system, so the type checker doesn't know that you're making this assumption.