Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I have an optional parameter in dataclasses that is omitted when transformed to dict?

I wish to perform static type checking (pylance in vscode) on some dictionaries. The "tricky" part is the I want some of the parameters to be optional and not show up at all in the dictionary. I've tried using dataclasses and TypedDict but without luck so far.

from typing import Optional, List
from dataclasses import dataclass, asdict


@dataclass
class SubOrder:
    name: str


@dataclass
class Order:
    name: str
    sub_orders: Optional[List[SubOrder]]


assert asdict(Order(name="Pizza")) == {"name": "Pizza"}
assert asdict(Order(name="Pizza", sub_orders=[SubOrder(name="Pasta")])) == {
    "name": "Pizza",
    "sub_orders": [{"name": "Pasta"}],
}

Is that achievable with dataclasses? I basically just want my static type checker (pylance / pyright) to check my dictionaries which is why I'm using dataclasses. I've tried with TypedDict as well but the type checkers does not seem to behave like I was. They always require me to set sub_orders.

The following code passes but pylance is not happy about not having sub_orders.

from typing import Optional, List, TypedDict


class SubOrder(TypedDict):
    name: str


class Order(TypedDict):
    name: str
    sub_orders: Optional[List[SubOrder]]


assert Order(name="Pizza") == {"name": "Pizza"}
assert Order(name="Pizza", sub_orders=[SubOrder(name="Pasta")]) == {
    "name": "Pizza",
    "sub_orders": [{"name": "Pasta"}],
}

EDIT

I've added a bug report in pylance since this might actually be a bug in pylance / pyright

like image 386
mr.bjerre Avatar asked Dec 03 '25 16:12

mr.bjerre


2 Answers

You can have an optional parameter in data class by setting a default value, for example an empty string "" or None.

from dataclasses import dataclass
from typings import Optional


@dataclass
class SubOrder:
    n: Optional[int] = None
    name: str = ""
like image 85
Pranu Pranav Avatar answered Dec 06 '25 14:12

Pranu Pranav


from dataclasses import asdict, dataclass
from typing import List, Optional

from validated_dc import ValidatedDC


@dataclass
class SubOrder(ValidatedDC):
    name: str


@dataclass
class Order(ValidatedDC):
    name: str
    sub_orders: Optional[List[SubOrder]] = None

    def as_dict(self):
        data = asdict(self)
        return {key: value for key, value in data.items() if value is not None}


data = {'name': 'pizza'}
order = Order(**data)
assert order.get_errors() is None
assert asdict(order) == {'name': 'pizza', 'sub_orders': None}
assert order.as_dict() == {'name': 'pizza'}

data = {'name': 'pizza', 'sub_orders': [{'name': 'pasta'}]}
order = Order(**data)
assert order.get_errors() is None
assert asdict(order) == {'name': 'pizza', 'sub_orders': [{'name': 'pasta'}]}
assert isinstance(order.sub_orders[0], SubOrder)

ValidatedDC - https://github.com/EvgeniyBurdin/validated_dc

like image 24
Evgeniy_Burdin Avatar answered Dec 06 '25 14:12

Evgeniy_Burdin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!