I have a Document and Page types, both containing data and metadata parts. They are looking the same:

```
class Document:
    __data: DocumentData
    __meta: DocumentMeta

    def __init__(self, part: Union[DocumentData, DocumentMeta, None] = None, data: Optional[DocumentData] = None,
             meta: Optional[DocumentMeta] = None):
        super().__init__()
        self.data: Optional[DocumentData] = data
        self.meta: Optional[DocumentMeta] = meta

        if part is not None:
            if type(part) == DocumentData:
                data = part
                meta = DocumentMeta()
            elif type(part) == DocumentMeta:
                meta = part
                data = DocumentData()    

class Page:
    __data: PageData
    __meta: PageMeta

    def __init__(self, part: Union[PageData, PageMeta, None] = None, data: Optional[PageData] = None,
             meta: Optional[PageMeta] = None):
        super().__init__()
        self.data: Optional[PageData] = data
        self.meta: Optional[PageMeta] = meta

        if part is not None:
            if type(part) == PageData:
                data = part
                meta = PageMeta()
            elif type(part) == PageMeta:
                meta = part
                data = PageData()

```

I would like now to refactor these 2 types to use a generic type. I did it that way:

```
from typing import Generic, Optional, TypeVar, Union

DataStruct = TypeVar('DataStruct')
MetaStruct = TypeVar('MetaStruct')

class MetaDataStruct(Generic[DataStruct, MetaStruct]):
    __data: DataStruct
    __meta: MetaStruct

    def __init__(
        self,
        part: Union[DataStruct, MetaStruct, None] = None,
        data: Optional[DataStruct] = None,
        meta: Optional[MetaStruct] = None
    ):
        super().__init__()
        self.data: Optional[DataStruct] = data
        self.meta: Optional[MetaStruct] = meta

        if part is not None:
            if type(part) == DataStruct:
                data = part
                meta = MetaStruct()
            elif type(part) == MetaStruct:
                meta = part
                data = DataStruct()

class DocumentData:
    pass

class DocumentMeta:
    pass

class PageData:
    pass

class PageMeta:
    pass

class Document(MetaDataStruct[DocumentData, DocumentMeta]):
    pass

class Page(MetaDataStruct[PageData, PageMeta]):
    pass

```

Now there's few problems with type checking. 

1. *if type(part) == DataStruct:* returns False all the time. In runtime a type(part) is one of: DocumentData, DocumentMeta, PageData, PageMeta. I understand that I have to compare type(part) with actual type of DataStruct. What is the right way to resolve the runtime type of DataStruct?  

In [python hints manual](https://docs.python.org/3/library/typing.html) it's written: *At runtime, isinstance(x, T) will raise TypeError. In general, isinstance() and issubclass() should not be used with types.* I believe the same issue is here. 

I can use *type(self).**orig\_bases**[0].**args**[0]* to infer DataStruct, but it is conceptually incorrect. It will retrieve the first generic argument instead DataStruct. So, if a MetaDataStruct base class signature will change to *class MergedStruct(Struct, Generic[MetaStruct, DataStruct])* (swapped TypeVar arguments), MetaStruct will be retrieved instead DataStruct.
2. For some reason, when I tried to intialize *Document(part=1)*, it passed. In practice I expected the code to raise TypeError.