How to handle typing of member variable that is initialized during __post_init__() of dataclass

Question:

The variable below is initialized as none, but during __post_init__ it is replaced with an instance of outlook client.

@dataclass
class Config:
    """Outlook configuration"""

    mailbox: str
    inbox: str
    mailbox_obj: Union["Mailbox", None] = None

However, static type analysis correctly informs that mailbox_obj has no members (…is not a known member of "None"). I don’t want to guard everything with if mailbox_obj just to satisfy the type analysis. Is there another way using a dataclass field or something?

The problem would go away if I just used a regular class since I can initialize the problem variable in init where the type will be inferred to it’s set value, but then I have to write that extra boilerplate.

Writing this question has reminded me of the below, which is probably what I’m looking for:

    mailbox_obj: "Mailbox" = field(init=False)

Is that the right way?

Asked By: appus3r

||

Answers:

Yes, you want to specify that it is not an init field, so you just want something like this:

import dataclasses

class Mailbox:
    pass

@dataclasses.dataclass
class Config:
    """Outlook configuration"""

    mailbox: str
    inbox: str
    mailbox_obj: "Mailbox" = dataclasses.field(init=False)

    def __post_init__(self):
        # do some stuff...
        self.mailbox_obj = Mailbox()

I saved the above code in a file called test_typing.py and here is mypy:

(py310) Juans-MBP:test juan$ mypy test_typing.py
Success: no issues found in 1 source file
Answered By: juanpa.arrivillaga