title: Type Hint Enum @classmethod That Returns Enum Member
body: <p>I've written an <code>enum.Enum</code> type with a couple of members. Now I want to write a "selector" <code>@classmethod</code> that will return one of the members of the <code>Enum</code> based on arguments, and <strong>I don't know how to type hint it properly</strong>.</p>
  
  <p>Here's what I have to far:</p>
  
  <pre class="lang-py prettyprint-override"><code>from enum import Enum, auto
  from typing import TypeVar, Type
  
  _StringSizeT = TypeVar("_StringSizeT", bound="StringSize")
  class StringSize(Enum):
  
      SMALL = auto()
      BIG = auto()
  
      @classmethod
      def from_string(cls: Type[_StringSizeT], source_string: str) -&gt; _StringSizeT:
          n_chars = len(source_string)
          if n_chars &lt;= 10:
              return cls.SMALL
          return cls.BIG
  </code></pre>
  
  <p>The above use of <code>TypeVar()</code>, etc is me trying to follow approach of <a href="https://stackoverflow.com/questions/39205527/can-you-annotate-return-type-when-value-is-instance-of-cls/39205612#39205612">Martijn Pieters' post in "Can you annotate return type when value is instance of cls?"</a> for <code>@classmethod</code> factories, but applying them to <code>Enum</code> <code>@classmethod</code>s that return one of the enum members.</p>
  
  <p>Unfortunately, mypy does not like the types of my return statements:</p>
  
  <pre><code>error: Incompatible return value type (got "StringSize", expected "_StringSizeT")
  </code></pre>
  
  <p>This is because the properties of this <code>@classmethod</code> are different than in that post: I'm not returning an <strong>instance</strong> of the class, but a <strong>class attribute</strong>, or in enum-speak, a member.</p>
  
  <p>How can I fix my method annotation here?</p>
  
  <p>UPDATE: Ok, while writing this, I riffed on the advice of mypy and found that </p>
  
  <pre class="lang-py prettyprint-override"><code>-&gt; "StringSize"
  </code></pre>
  
  <p>is acceptable. This is a little confusing because, again, I'm not returning an instance, but I'll chalk that up to the metaprogramming machinery underneath <code>Enum</code>. <strong>Followup: Is there a non-string-literal type annotation I could use here instead?</strong> Through my experience, I've learned (maybe incorrectly) to dislike the string literal annotations. (Am I sacrificing anything with them?)</p>