title: Does mypy have a Subclass-Acceptable Return Type?
body: <p>I'm wondering how (or if it is currently possible) to express that a function will return a subclass of a particular class that is acceptable to mypy?</p>
  
  <p>Here's a simple example where a base class <code>Foo</code> is inherited by <code>Bar</code> and <code>Baz</code> and there's a convenience function <code>create()</code> that will return a subclass of <code>Foo</code> (either <code>Bar</code> or <code>Baz</code>) depending upon the specified argument:</p>
  
  <pre class="lang-py prettyprint-override"><code>class Foo:
      pass
  
  
  class Bar(Foo):
      pass
  
  
  class Baz(Foo):
      pass
  
  
  def create(kind: str) -&gt; Foo:
      choices = {'bar': Bar, 'baz': Baz}
      return choices[kind]()
  
  
  bar: Bar = create('bar')
  </code></pre>
  
  <p>When checking this code with mypy the following error is returned:</p>
  
  <p><strong>error: Incompatible types in assignment (expression has type "Foo", variable has type "Bar")</strong></p>
  
  <p>Is there a way to indicate that this should be acceptable/allowable. That the expected return of the <code>create()</code> function is not (or may not be) an instance of <code>Foo</code> but instead a subclass of it?</p>
  
  <p>I was looking for something like:</p>
  
  <pre class="lang-py prettyprint-override"><code>def create(kind: str) -&gt; typing.Subclass[Foo]:
      choices = {'bar': Bar, 'baz': Baz}
      return choices[kind]()
  </code></pre>
  
  <p>but that doesn't exist. Obviously, in this simple case, I could do:</p>
  
  <pre class="lang-py prettyprint-override"><code>def create(kind: str) -&gt; typing.Union[Bar, Baz]:
      choices = {'bar': Bar, 'baz': Baz}
      return choices[kind]()
  </code></pre>
  
  <p>but I'm looking for something that generalizes to N possible subclasses, where N is a number larger than I want to be defining as a <code>typing.Union[...]</code> type.</p>
  
  <p>Anyone have any ideas on how to do that in a non-convoluted way?</p>
  
  <hr>
  
  <p>In the likely case that there is no non-convoluted way to do this, I am aware of a number of less-than-ideal ways to circumvent the problem:</p>
  
  <ol>
  <li>Generalize the return type:</li>
  </ol>
  
  <pre class="lang-py prettyprint-override"><code>def create(kind: str) -&gt; typing.Any:
      ...
  </code></pre>
  
  <p>This resolves the typing problem with the assignment, but is a bummer because it reduces the type information of the function signature's return.</p>
  
  <ol start="2">
  <li>Ignore the error:</li>
  </ol>
  
  <pre class="lang-py prettyprint-override"><code>bar: Bar = create('bar')  # type: ignore
  </code></pre>
  
  <p>This suppresses the mypy error but that's not ideal either. I do like that it makes it more explicit that the <code>bar: Bar = ...</code> was intentional and not just a coding mistake, but suppressing the error is still less than ideal.</p>
  
  <ol start="3">
  <li>Cast the type:</li>
  </ol>
  
  <pre class="lang-py prettyprint-override"><code>bar: Bar = typing.cast(Bar, create('bar'))
  </code></pre>
  
  <p>Like the previous case, the positive side of this one is that it makes the <code>Foo</code> return to <code>Bar</code> assignment more intentionally explicit. This is probably the best alternative if there's no way to do what I was asking above. I think part of my aversion to using it is the clunkiness (both in usage and readability) as a wrapped function. Might just be the reality since type casting isn't part of the language - e.g <code>create('bar') as Bar</code>, or <code>create('bar') astype Bar</code>, or something along those lines.</p>