I have this Pydantic model: import typing import pydantic class TypeAData(pydantic.BaseModel): aStr: str class TypeBData(pydantic.BaseModel): bNumber: int class TypeCData(pydantic.BaseModel): cBoolean: bool class MyData(pydantic.BaseModel): type: typing.Literal['A', 'B', 'C'] name: str data: TypeAData | TypeBData | TypeCData However, if type is equal to "A" and data contains TypeBData, it'll validate correctly when it shouldn't. This could be an alternative: class MyData(pydantic.BaseModel): type: typing.Literal['A', 'B', 'C'] name: str data: TypeAData | TypeBData | TypeCData @pydantic.validator('data', pre=True, always=True) def validate_data(cls, data): if isinstance(data, dict): data_type = data.get('type') if data_type == 'A': return TypeAData(**data) elif data_type == 'B': return TypeBData(**data) elif data_type == 'C': return TypeCData(**data) raise ValueError('Invalid data or type') It works; however, is there a better way to do it without repeating the enum keys ('A', 'B' and 'C') and values (TypeAData, TypeBData and TypeCData) twice? I've tried using discriminated unions, but since the type field and the discriminated fields are in different levels within the model (the latter is inside a nested object), I could not make further progress on this. Continue reading...