How to create a Generic Type where the output is the inner type?

I want to use custom types to annotate functions. Example:

@dataclass
class CurrencyPosition:
    owner: str
def read_balance(balance: Form[CurrencyPosition]) -> None:
    print(balance.owner)

However can’t figure out the correct type for balance. I tried to create a custom generic:

T = typing.TypeVar("T")
class Form(typing.Generic[T]):
    ...

But all attributes from the inner type get’s shadowed.

This works but I can’t restrict the type:

Form = typing.Union[T, typing.Type[T]]

Firstly, you can apply a bound to a type variable, so all concrete substitutions must be an instance of the provided bound; see the docs.

Second, generics are a way to parameterise shape attributes (method signatures, property types, etc). In your example, you would be customised the type of specific attributes of Form instances.

However in your example you’re not using a form instance: it looks like you want one of the following:

  1. Change the signature such that only one type is accepted: balance: CurrencyPosition (note: subclasses would be accepted)

  2. Pass in form instance instead:

    def read_balance(form: Form[CurrencyPosition]) -> None:
        print(form.balance.owner)
    
    class Form(Generic[T]):
        balance: T
    
  3. Use a protocol (Python 3.8+):

    class Balance(Protocol):
        owner: str
    
    def read_balance(balance: Balance) -> None:
        print(balance.owner)
    

The option 2 is the closest to what I want. Form would have special methods in addition to T properties but to make that happen is there any way to make Form inherit the attributes of T? Like:

class Form(Generic[T], T): ...

Proxy and dynamic attributes are out of the scope for static type checking. In addition, TypeVar is not supposed to be inherited (the fact that it is a class is an implementation detail: it should raise an error if you try). Pretend all typing is invisible to runtime (unless you’re doing inspection, which is likely never for most users).

In my IDE (PyCharm), implementing __getattr__ (in this case for attribute proxying) makes the type-checker assume all attributes are valid.

I think you want to use a protocol, with the attributes and special methods required for read_balance. At runtime, your Form would implement that protocol (with either Balance as a parent class, or an instance of Balance as an instantiation parameter and property).