title: How do I type-hint that a Python function returns instance of any class derived from a superclass?
body: <p>I've got a bunch of Django template inclusion tags, which take as an argument either a specific instance of a database object or a string/int, which is interpreted as the primary key of that database object. For example...</p>
  
  <pre><code>{% render_product product=obj %}
  {% render_product product=42 %}
  {% render_product product="42" %}
  </code></pre>
  
  <p>...all work fine and do the obvious: they render a template fragment with a particular Product instance, fetching it by primary key from the database, if needed. This is how Product and similar classes are defined:</p>
  
  <pre><code>class Product(models.Model):
      # standard django model definition goes here
  </code></pre>
  
  <p>Here's what usually happens in such an inclusion tag:</p>
  
  <pre><code>@register.inclusion_tag("render_product.html")
  def render_product(product: Union[Product, str, int] = None) -&gt; dict:
      _product = None
      if isinstance(product, Product):
          _product = product
      elif isinstance(product, str) or isinstance(product, int):
          try:
              _product = Product.objects.get(pk=product)
          except (Product.DoesNotExist, ValueError):
              pass
      return {"product": _product}
  </code></pre>
  
  <p>Since I've got the same pattern happening in dozens of inclusion tags, I'm trying to refactor it out, so that I've got something like:</p>
  
  <pre><code>@register.inclusion_tag("render_product.html")
  def render_product(product: Union[Product, str, int] = None) -&gt; dict:
      _product = fetch_object(Product, product)
      return {"product": _product}
  </code></pre>
  
  <p>Here's the fetch_object code:</p>
  
  <pre><code>def fetch_object(cls: Type[Model] = None, obj: Union[Model, str, int] = None):
      if isinstance(obj, cls):
          return obj
      elif isinstance(obj, str) or isinstance(obj, int):
          try:
              return cls.objects.get(pk=obj)
          except (cls.DoesNotExist, ValueError):
              pass
      return None
  </code></pre>
  
  <p>My problem is: I have no idea how to specify the return type of that function. Basically it should be something like "instance of any class, which is derived from Model or None". But if I try something like...</p>
  
  <pre><code>def fetch_object(
      cls: Type[Model] = None, obj: Union[Model, str, int] = None
  ) -&gt; Union[Model, None]:
  </code></pre>
  
  <p>...then PyCharm complains about "unresolved attribute reference" if I access a method on the fetched object, which is Product-specific, not Model-specific.</p>
  
  <p>I'm trying to use more and more type-hinting in my Python code, because it has already saved my butt a few times, but this is one of those cases, where I have no idea what the correct way of doing it would be and my google-fu is failing me.</p>
  
  <p>What is the correct type-hinting for fetch_object?</p>