0

Is there a way to assign all fields from a base dataclass to another one such that MyPy understands which fields are present?

from dataclasses import dataclass

@dataclass
class TypeA:
  name: str
  age: int

@dataclass
class TypeB(TypeA):
  more: bool


def upgrade(a: TypeA) -> TypeB:
  return TypeB(
     more=False,
     **a,  # this is syntax I'm uncertain of
  )

I can use ** on a dataclasses.asdict or the __dict__ field, but that erases the type checking. For example, MyPy doesn't complain about this:

  return TypeB(
     **a.__dict__
  )

Despite more being missing. It appears that MyPy loses type information on __dict__ (as well as dataclasses.asdict).

I don't want to list individual fields for copying for two reasons:

  • It's redundant
  • I may miss an optional field which would not be caught
  • I may later add an optiona/default field which would not be detected
Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
edA-qa mort-ora-y
  • 30,295
  • 39
  • 137
  • 267
  • Does this answer your question? [Python: Dataclass that inherits from base Dataclass, how do I upgrade a value from base to the new class?](https://stackoverflow.com/questions/54824893/python-dataclass-that-inherits-from-base-dataclass-how-do-i-upgrade-a-value-fr) – Axe319 Sep 14 '21 at 12:50
  • On second thought, the voted best answer utilizes `asdict` which you're specifically trying to avoid. But some of the answers there may be helpful. – Axe319 Sep 14 '21 at 12:54
  • I'm unclear why it wouldn't work how you were planning, i.e. `return TypeB(more=a.__dict__.pop('more', False), **a.__dict__, )` – rv.kvetch Sep 14 '21 at 20:47
  • @rv.kvetch That erases the type information in mypy. There is no checking done if the dataclass being copied has the right fields, is missing fields, or are of the correct type. Basically MyPy does not type checking when you use `**a.__dict__`. My question is how can I do this with type safety? – edA-qa mort-ora-y Sep 15 '21 at 08:29
  • 2
    @Axe319 They do copy the values, and I use them. But I lose MyPy type safety when I use that approach. – edA-qa mort-ora-y Sep 15 '21 at 08:29
  • 3
    As far as I can tell, this is not possible without explicitly writing out the fields. ``**`` dict unpacking – currently – looses all field information, and there is no alternative akin to "attribute unpacking". – MisterMiyagi Sep 15 '21 at 09:00

0 Answers0