This should work:

from typing import *

T = TypeVar('T')  # Any type.
ValueOrCallable = Union[T, Callable[..., T]]

class Foo(object):
  state:  ClassVar[ValueOrCallable]

Answer from Victor Ruiz on Stack Overflow
🌐
Python
typing.python.org › en › latest › spec › aliases.html
Type aliases — typing documentation
Type parameters declared as part of a generic type alias are valid only when evaluating the right-hand side of the type alias. As with typing.TypeAlias, type checkers should restrict the right-hand expression to expression forms that are allowed within type annotations.
🌐
GitHub
github.com › python › typing › discussions › 1850
Mypy: how to use type aliases in generic classes · python/typing · Discussion #1850
In your code sample, you've defined the type alias T_c_wo as a generic type alias that has three generic type parameters. When you use T_c_wo, you should provide three type arguments. These type arguments can include type variables that are scoped to your local function or class. For example: x: T_c_wo[int, ..., str] or x: T_c_wo[T_o_wo, P_wo, T_ret_wo]. If you use T_c_wo by itself with non subscript, it will be interpreted as T_c_wo[Any, ..., Any]. That's probably not what you intend.
Author   python
🌐
Python
typing.python.org › en › latest › reference › generics.html
Generics — typing documentation
Type aliases can be generic. In this case they can be used in two ways: Subscripted aliases are equivalent to original types with substituted type variables, so the number of type arguments must match the number of free type variables in the generic type alias.
🌐
Mypy
mypy.readthedocs.io › en › stable › generics.html
Generics - mypy 1.19.1 documentation
Type aliases defined using the new syntax can’t be used as base classes and can’t be used to construct instances, unlike aliases defined using the old syntax. You may wonder what happens at runtime when you index a generic class. Indexing returns a generic alias to the original class that returns instances of the original class on instantiation (Python 3.12 syntax):
🌐
Sorokin
sorokin.engineer › posts › en › python_type_aliasing.html
Generic type aliasing in Python
When you use List[Animal] you actually use list with specific items types and without type argument that has its parent, generic list. That’s why now there is just no place where to specify type for AnimalList items, this is not generic list anymore. The solution is extremely simple. Create type alias for Animal.
🌐
GitHub
github.com › python › typing › discussions › 1345
Type alias in generic class using bound type variable · python/typing · Discussion #1345
The maintainers of the major type checker came to an agreement that type aliases should be allowed within classes but not within functions. What you're doing here (attempting to define a class-scoped type alias that uses an outer-scoped bound type variable) is not supported by Python type checkers today.
Author   python
🌐
GitHub
github.com › python › mypy › issues › 1037
Generic type alias? · Issue #1037 · python/mypy
December 2, 2015 - Not sure if this is Question or Issue. Is the IterFunc alias below allowed? There is no other way to alias a complex generic types. from typing import TypeVar, Callable, Iterator, Iterable T = TypeVar("T") IterFunc = Callable[[], Iterato...
Published   Dec 02, 2015
Find elsewhere
🌐
Python documentation
docs.python.org › 3 › library › typing.html
typing — Support for type hints
TypeAlias is particularly useful on older Python versions for annotating aliases that make use of forward references, as it can be hard for type checkers to distinguish these from normal variable assignments: from typing import Generic, TypeAlias, TypeVar T = TypeVar("T") # "Box" does not exist yet, # so we have to use quotes for the forward reference on Python <3.12.
🌐
JetBrains
youtrack.jetbrains.com › issue › PY-29257 › Support-partially-specialized-and-generic-type-aliases
Support partially specialized and generic type aliases
{{ (>_<) }} This version of your browser is not supported. Try upgrading to the latest stable version. Something went seriously wrong
🌐
Mathspp
mathspp.com › blog › til › type-statement-and-type-aliases
TIL #084 – type statement and type aliases | mathspp
Type aliases can also be made generic. For example, the linked list could be a linked list of any kind of value we want, not just integers. ... This means that a linked list is either a value of its type T or it is a pair with a value and a ...
🌐
Python
peps.python.org › pep-0695
PEP 695 – Type Parameter Syntax | peps.python.org
This PEP proposes to eliminate ... declaration statement. Generic type aliases are often misused because it is not clear to developers that a type argument must be supplied when the type alias is used....
🌐
Python.org
discuss.python.org › python help
types.GenericAlias vs typing._GenericAlias - Python Help - Discussions on Python.org
August 12, 2024 - Hi, today I found a surprising fact that types.GenericAlias and typing._GenericAlias are different. Seems user defined generic uses typing._GenericAlias and builtin types uses types.GenericAlias >>> type(list[int]) <c…
🌐
GitHub
github.com › python › mypy › issues › 697
Is there a way to type-alias a generic type? · Issue #697 · python/mypy
January 4, 2015 - Can I write a generic type-aliase so that: MyBundle[t] is exactly equivalent to Tuple[List[t], t, List[t]]
Published   May 27, 2015
🌐
Python.org
discuss.python.org › python help
PEP 695 type aliases not suitable as replacement for typing.TypeAlias? - Page 2 - Python Help - Discussions on Python.org
January 18, 2024 - Also to answer this question. I would use explicit aliases and PEP695 aliases in exactly the same way: To give a more succinct, descriptive name to complex type expressions that repeatedly appear in type annotations, it’s also handy for generic unions, to avoid having to repeat the same type parameter over and over again inside a type expression.
🌐
Python.org
discuss.python.org › python help
Static Enforced Non generic Type alias? - Python Help - Discussions on Python.org
February 6, 2024 - From the pep 484, we have this code (now modernized): type Url = str def retry(url: Url, retry_count: int) -> None: ... But I didn´t find any reference of this aliases should/ are enforced in static analysis. for ins…
🌐
Runebook.dev
runebook.dev › en › docs › python › library › typing › typing.TypeAliasType.__type_params__
New-Style Generic Type Aliases in Python 3.12: Common Issues
The __type_params__ attribute is a tuple that holds the type variables (TypeVar, ParamSpec, TypeVarTuple) that parameterize the generic type alias. It allows for runtime introspection (checking what the type parameters are). Here's how you might see it work (though you typically wouldn't access this attribute directly in day-to-day code) # This new syntax is available in Python 3.12+ from typing import TypeVar, get_type_hints # 1.
🌐
Stack Overflow
stackoverflow.com › questions › 72843258 › generic-type-aliases-w-r-t-generic-class-parameter
python - Generic Type Aliases w.r.t. Generic Class Parameter - Stack Overflow
T = TypeVar("T") U = TypeVar("U") V = TypeVar("V") W = TypeVar("W") class Bar(Generic[T, U, V]): ... class Foo(Generic[T, U, V, W]): def do_something(self, x: Bar[T, U, V], y: W) -> Bar[T, U, V]: reveal_type(x) # note: Revealed type is "Bar[T`1, U`2, V`3]" A bit contrived, but the point is, Foo performs lots of operations on a highly parametrized Bar and it would be nice to not have to repeat Bar[T, U , V] everywhere (especially because in the real code the TypeVars have long names).
🌐
Real Python
realpython.com › ref › glossary › type-alias
type alias | Python Glossary – Real Python
In Python, a type alias allows you to create an alternative name for an existing type. It’s a convenient way to make your type hints more readable. You can create a type alias by assigning a type to a variable name.