I'm trying to represent physical dimensions (length, time, temperature, ...), and cannot find a nice way to do so, that is compatible with type hinting and generics. Ideally, I want to be able to define an Enum whose names are types themselves (a metaenum ?): from enum import Enum class Dim(Enum): TIME = "t" MASS = "m" I can type hint dimensions (dim: Dim) but cannot do things like from typing import Generic, TypeVar T = TypeVar("T", bound=Dim) # only accepts `Dim` class PhysicalQuantity(Generic[T]): pass class Container: some_time: PhysicalQuantity[Dim.TIME] # doesn't work because these are values. Is there a construct as simple as Enum, but to make types instead of values ? Reasons why I want to keep Enum: very easy to define very easy to associate to a value (str) Ability to sort of "think of Dim as the type, and Dim.TIME as a subtype" There are functional solutions, however I'm asking this to get a "best way" more than a "working way". Here's what I found: The simplest solution is to do use Literal: SomeGenericType[Literal[Dim.TIME]], but this is both annoying to write each time and counter-intuitive for people who expect Dim.TIME to behave as a type. Switching to classes, the most intuitive idea: class Dimension: pass class TIME(Dimension): pass doesn't work, because I want type(TIME) to be Dim, to reproduce Enum behavior That leads to using a metaclass: class Dimension(type): # ... complete __init__ and __new__ to get TIME.symbol = "t" class TIME(metaclass=Dimension, symbol="t"): pass This works, but I lose the ability to do Dim.TIME, to get Dim.TIME from Dim('t'), ... Continue reading...