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"}],
}
I've added a bug report in pylance since this might actually be a bug in pylance / pyright
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 = ""
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With