title: Pydantic is confused with my types and their union
body: <p>I have following Pydantic model type scheme specification:</p>
  <pre class="lang-py prettyprint-override"><code>class RequestPayloadPositionsParams(BaseModel):
      &quot;&quot;&quot;
      Request payload positions parameters
      &quot;&quot;&quot;
  
      account: str = Field(default=&quot;COMBINED ACCOUNT&quot;)
      fields: List[str] = Field(default=[&quot;QUANTITY&quot;, &quot;OPEN_PRICE&quot;, &quot;OPEN_COST&quot;])
  
  
  class RequestPayloadPositions(BaseModel):
      &quot;&quot;&quot;
      Request payload positions service
      &quot;&quot;&quot;
  
      header: RequestPayloadHeader = Field(
          default=RequestPayloadHeader(service=&quot;positions&quot;, id=&quot;positions&quot;, ver=0)
      )
      params: RequestPayloadPositionsParams = Field(
          default=RequestPayloadPositionsParams()
      )
  
  
  class RequestPayloadOrdersParams(BaseModel):
      &quot;&quot;&quot;
      Request payload orders parameters
      &quot;&quot;&quot;
  
      account: str = Field(default=&quot;COMBINED ACCOUNT&quot;)
      types: List[str] = Field(default=[&quot;WORKING&quot;, &quot;FILLED&quot;, &quot;CANCELED&quot;])
  
  
  class RequestPayloadOrders(BaseModel):
      &quot;&quot;&quot;
      Request payload orders service
      &quot;&quot;&quot;
  
      header: RequestPayloadHeader = Field(
          default=RequestPayloadHeader(service=&quot;order_events&quot;, id=&quot;order_events&quot;, ver=0)
      )
      params: RequestPayloadOrdersParams = Field(default=RequestPayloadOrdersParams())
  
  
  class RequestPayload(BaseModel):
      &quot;&quot;&quot;
      Request payload data
      &quot;&quot;&quot;
  
      payload: List[Union[RequestPayloadPositions, RequestPayloadOrders]] = Field(...)
  </code></pre>
  <p>Now, I want to create a payload object for both, orders and positions service:</p>
  <pre class="lang-py prettyprint-override"><code>positions = requests.RequestPayload(payload=[requests.RequestPayloadPositions()])
  orders = requests.RequestPayload(payload=[requests.RequestPayloadOrders()])
  </code></pre>
  <p>Now, <code>positions</code> has type <code>requests.RequestPayload[payload= requests.RequestPayloadPositions</code> ... but <code>orders</code> has not <code>requests.RequestPayload[payload= requests.RequestPayloadOrders</code> but the same like <code>positions</code>.
  This is wrong.</p>
  <p>I can fix this by change the model specification from <code>payload: List[Union[RequestPayloadPositions, RequestPayloadOrders]] = Field(...)</code> to <code>payload: List[Any] = Field(...)</code> ... but I want to explicitly define the allowed types.</p>
  <p>Any idea how to solve this, or should I explain more detailed? Do you understand my problem?</p>
  <p><strong>EDIT</strong>
  Working code sample, shows that the second assert in the last line fails, but should not fail ...</p>
  <pre class="lang-py prettyprint-override"><code>from typing import List, Union
  from pydantic import BaseModel, Field
  
  
  class RequestPayloadHeader(BaseModel):
      &quot;&quot;&quot;
      Request payload header
      &quot;&quot;&quot;
  
      service: str = Field(...)
      id: str = Field(...)
      ver: int = Field(...)
  
  
  class RequestPayloadLoginParams(BaseModel):
      &quot;&quot;&quot;
      Request payload login parameters
      &quot;&quot;&quot;
  
      domain: str = Field(default=&quot;TOS&quot;)
      platform: str = Field(default=&quot;PROD&quot;)
      token: str = Field(...)
      accessToken: str = Field(default=&quot;&quot;)
      tag: str = Field(default=&quot;TOSWeb&quot;)
  
  
  class RequestPayloadLogin(BaseModel):
      &quot;&quot;&quot;
      Request payload login service
      &quot;&quot;&quot;
  
      header: RequestPayloadHeader = Field(
          default=RequestPayloadHeader(service=&quot;login&quot;, id=&quot;login&quot;, ver=0)
      )
      params: RequestPayloadLoginParams = Field(...)
  
  
  class RequestPayloadPositionsParams(BaseModel):
      &quot;&quot;&quot;
      Request payload positions parameters
      &quot;&quot;&quot;
  
      account: str = Field(default=&quot;COMBINED ACCOUNT&quot;)
      fields: List[str] = Field(default=[&quot;QUANTITY&quot;, &quot;OPEN_PRICE&quot;, &quot;OPEN_COST&quot;])
  
  
  class RequestPayloadOrdersParams(BaseModel):
      &quot;&quot;&quot;
      Request payload orders parameters
      &quot;&quot;&quot;
  
      account: str = Field(default=&quot;COMBINED ACCOUNT&quot;)
      types: List[str] = Field(default=[&quot;WORKING&quot;, &quot;FILLED&quot;, &quot;CANCELED&quot;])
  
  
  class RequestPayloadService(BaseModel):
      &quot;&quot;&quot;
      Request payload service
      &quot;&quot;&quot;
  
      header: RequestPayloadHeader = Field(...)
      params: Union[RequestPayloadPositionsParams, RequestPayloadOrdersParams] = Field(
          ...
      )
  
  
  class RequestPayload(BaseModel):
      &quot;&quot;&quot;
      Request payload data
      &quot;&quot;&quot;
  
      payload: List[Union[RequestPayloadLogin, RequestPayloadService]] = Field(...)
  
  
  if __name__ == &quot;__main__&quot;:
      positions = RequestPayload(
          payload=[
              RequestPayloadService(
                  header=RequestPayloadHeader(service=&quot;positions&quot;, id=&quot;positions&quot;, ver=0),
                  params=RequestPayloadPositionsParams(),
              )
          ]
      )
      assert isinstance(positions.payload[0].params, RequestPayloadPositionsParams)
      orders = RequestPayload(
          payload=[
              RequestPayloadService(
                  header=RequestPayloadHeader(
                      service=&quot;order_events&quot;, id=&quot;order_events&quot;, ver=0
                  ),
                  params=RequestPayloadOrdersParams(),
              )
          ]
      )
      assert isinstance(orders.payload[0].params, RequestPayloadOrdersParams)
  </code></pre>
  <p><strong>EDIT2</strong>
  The solution by Alex does not cover the scenario when I have two models with same field names but different types for them, like this:</p>
  <pre class="lang-py prettyprint-override"><code>class ResponseReplacePatchStr(BaseModel):
      op: str = Field(default=&quot;replace&quot;)
      path: str = Field(...)
      value: str = Field(...)
  
      class Config:
          extra = &quot;forbid&quot;
  
  class ResponseReplacePatchFloat(BaseModel):
      op: str = Field(default=&quot;replace&quot;)
      path: str = Field(...)
      value: float = Field(...)
  
      class Config:
          extra = &quot;forbid&quot;
  </code></pre>
  <p>It is always converted to type <code>str</code> for <code>value</code> field if <code>ResponseReplacePatchStr</code> is the first type mentioned in</p>
  <pre class="lang-py prettyprint-override"><code>Union[
              ResponseReplacePatchStr, ResponseReplacePatchFloat
          ]
  </code></pre>
  <p>How can I also solve this, so that Pydantic take care about my types?</p>