Python の TypeVarTuple(可変長ジェネリクス)

TypeVarTuple は Python 3.11 で導入され、可変長のジェネリック型パラメータを表現できます。任意個の型を受け取る関数やクラスの型付けが可能になります。

基本的な使い方

from typing import TypeVarTuple, Unpack

Ts = TypeVarTuple("Ts")

def first(*args: Unpack[Ts]) -> tuple[Unpack[Ts]]:
    return args

Ts は 0 個以上の型のシーケンスを表します。

タプルの型付け

from typing import TypeVarTuple, Generic, Unpack

Ts = TypeVarTuple("Ts")

class MyTuple(Generic[Unpack[Ts]]):
    def __init__(self, *args: Unpack[Ts]):
        self.items: tuple[Unpack[Ts]] = args
    
    def get_all(self) -> tuple[Unpack[Ts]]:
        return self.items

t = MyTuple(1, "hello", 3.14)
# 型は MyTuple[int, str, float]

関数の合成

複数の関数を合成する際に、中間の型を保持できます。

from typing import TypeVarTuple, Callable, Unpack

Ts = TypeVarTuple("Ts")
R = TypeVar("R")

def apply_all(
    value: int,
    *funcs: Unpack[tuple[Callable[[int], int], ...]]
) -> int:
    result = value
    for func in funcs:
        result = func(result)
    return result

実用例:zip の型付け

from typing import TypeVarTuple, Unpack, Iterator

Ts = TypeVarTuple("Ts")

def typed_zip(
    *iterables: Unpack[tuple[list[int], list[str], list[float]]]
) -> Iterator[tuple[int, str, float]]:
    return zip(*iterables)

制約と注意点

TypeVarTuple は 1 つのシグネチャに 1 つまで
Unpack は TypeVarTuple の展開に使う
Python 3.11 以降でのみ使用可能
型チェッカーのサポート状況は確認が必要

TypeVarTuple は NumPy の ndarray のような多次元配列、可変長引数を持つ関数、タプル操作のユーティリティなど、複雑な型を正確に表現するのに役立ちます。