Unwrapping types

I have a function that takes a tuple of a wrapping type, and it returns a type using the tuple of the unwrapped types.

Conceptually it would be something like the following, where the types of each element in the tuple can be different.

def all(*args: tuple[Input[T1], Input[T2], Input[T3], ...] -> Output[tuple[T1, T2, T3, ...]]: ...

TypeVarTuple looks almost like what I’d need, but I don’t see how to deal with the additional Input wrapper that I have.

This can’t be done yet, we need something like a Map construct, which used to be part of the TypeVarTuple PEP originally, but was later removed to keep the scope limited. Since it was already going to be very complex to implement for type checkers without Map.

With Map you could write it like this:

def all(*args: *Map[Input, Ts]) -> Output[tuple[*Ts]]: ...

In the meantime you can use typing.overload to define the most common case for mixed inputs up to N and add a uniform fallback for above N.

@overload
def all() -> Output[tuple[()]]: ...
@overload
def all(a1: Input[T1], /) -> Output[tuple[T1]]: ...
@overload
def all(a1: Input[T1], a2: Input[T2], /) -> Output[tuple[T1, T2]]: ...
@overload
def all(a1: Input[T1], a2: Input[T2], a3: Input[T3], /) -> Output[tuple[T1, T2, T3]]: ...
# fallback
@overload
def all(a1: Input[T], a2: Input[T], a3: Input[T], a4: Input[T], /, *args: Input[T]) -> Output[tuple[T, ...]]: ...

This is how common functions in the standard library like map are currently written in typeshed as well.

1 Like