数学講師2852771 views
高校生物549842 views
ヒストリア284143 views
英語607877 views
高校化学2913383 views
りんご192546 views
MathPython491378 views
高校倫理1433119 views
小学算数1194618 views
小学社会308636 views
Help
Tools

English

TypeAlias で型に名前をつける

型ヒントが複雑になってくると、同じ型を何度も書く場面が増えてくる。dict[str, list[tuple[int, int]]] のような型を関数ごとに繰り返し書くのは読みにくいし、変更があったときに修正箇所が散らばってしまう。TypeAlias を使えば、複雑な型に分かりやすい名前を付けて一元管理できる。

単純な型エイリアス

最もシンプルな型エイリアスは、変数に型を代入するだけで作れる。

UserId = int
Username = str

def find_user(uid: UserId) -> Username | None:
    users: dict[UserId, Username] = {1: "Alice", 2: "Bob"}
    return users.get(uid)

UserIdUsername は int や str の別名にすぎないが、コードの意図が格段に伝わりやすくなる。ただし、この書き方だと型チェッカが「これは型エイリアスなのか、それとも普通の変数なのか」を判断しにくいことがある。

TypeAlias による明示的な宣言

Python 3.10 で導入された TypeAlias を使えば、「これは型エイリアスである」と明示できる。

from typing import TypeAlias

UserId: TypeAlias = int
ScoreList: TypeAlias = list[int]
UserScores: TypeAlias = dict[str, ScoreList]
暗黙の型エイリアス

UserId = int — 型エイリアスか変数代入か、見た目では区別しにくい。

明示的な TypeAlias

UserId: TypeAlias = int — 型エイリアスであることが一目でわかる。型チェッカも正確に解釈する。

TypeAlias を使うことで、コードを読む人にも型チェッカにも意図が正確に伝わるようになる。

Python 3.12 の type 文

Python 3.12 ではさらに簡潔な type 文が導入された。

type UserId = int
type ScoreList = list[int]
type UserScores = dict[str, ScoreList]

type 文は TypeAlias のインポートすら不要で、最もすっきりした書き方になる。3.12 以降を使えるプロジェクトならこちらが推奨される。

3.9以前
暗黙の型エイリアス

UserId = int のように変数代入で型エイリアスを表現。typing モジュールのインポートは不要だが、意図が曖昧。

3.10
TypeAlias の導入

UserId: TypeAlias = int で型エイリアスを明示的に宣言可能に。

3.12
type 文の導入

type UserId = int でインポート不要の専用構文が追加。最も簡潔。

複雑な型に名前を付ける

TypeAlias の真価は、ネストした複雑な型を整理するときに発揮される。

from typing import TypeAlias

# エイリアスなし — 読みにくい
def process(data: dict[str, list[tuple[int, int]]]) -> list[dict[str, float]]:
    ...

# エイリアスあり — 意味が明確
CoordList: TypeAlias = list[tuple[int, int]]
RegionData: TypeAlias = dict[str, CoordList]
StatResult: TypeAlias = list[dict[str, float]]

def process(data: RegionData) -> StatResult:
    ...

エイリアスに適切な名前を付ければ、型の構造だけでなくドメインの概念まで伝えられる。RegionData という名前からは「地域ごとのデータ」という意味が読み取れるが、dict[str, list[tuple[int, int]]] からは何も伝わらない。

コールバック関数の型にも使える

関数を引数に取るような場面でも型エイリアスは有効だ。

from typing import TypeAlias
from collections.abc import Callable

Handler: TypeAlias = Callable[[str, int], bool]

def register(name: str, handler: Handler) -> None:
    ...

Callable[[str, int], bool] を毎回書くよりも、Handler という名前で扱えるほうが見通しがよい。引数が多い Callable ほどエイリアスの恩恵は大きくなる。

型エイリアスの注意点

型エイリアスはあくまで「別名」であり、新しい型を作るわけではない。

from typing import TypeAlias

UserId: TypeAlias = int
age: UserId = 25  # int なので当然通る

UserIdint は型チェッカ上まったく同じ扱いになるため、UserId を期待する場所に普通の int を渡してもエラーにならない。型レベルで区別したい場合は NewType を使う手があるが、それはまた別の話になる。

TypeAlias は別名を作る

既存の型に読みやすい名前を付ける。型チェック上の区別はない。

NewType は新しい型を作る

既存の型を基にした「別の型」を定義する。型チェッカが区別してくれる。

型エイリアスは「同じ型を何度も書くのを避ける」「複雑な型に意味のある名前を付ける」ためのツールだ。プロジェクトの規模が大きくなるほど、整理された型エイリアスの存在がコードの可読性を大きく左右する。