型ヒントは、Python のコードに「期待する型」を書き添えるしくみです。本記事では基本の書き方から、Optional や TypedDict などのよく使うパターンを整理します。生成AI と一緒にコードを書くときにも、型ヒントは強い手がかりになります。
目次
- 型ヒントとは
- 基本の型
- Optional と Union — 値がないかもしれない
- Any — 何でも受ける(最後の手段)
- Callable — 関数を受け取る
- TypedDict — 辞書のキーごとに型を決める
- dataclass の型ヒント
- 型チェッカーで検査する
- 生成AI に読み書きしやすいコードのために
- やりすぎない
型ヒントとは
型ヒントは「この変数や関数の引数は何の型か」を書き添える記法です。
price: int = 1500name: str = "トヨタ自動車"prices: list[float] = [2900.0, 2925.0]
def average(values: list[float]) -> float: return sum(values) / len(values)押さえたいポイントは次の 2 つです。
- 型ヒントは 実行時にチェックされない(注釈にすぎない)
- ただし エディタや型チェッカーが活用 し、生成AI も意図を読み取りやすくなる
基本の型
組み込みの型はそのまま書けます。
i: int = 1f: float = 1.5s: str = "7203"b: bool = Truen: None = Noneコレクション型はカッコ [ ] の中に要素の型を書きます。Python 3.9 以降は組み込み型の小文字版がそのまま使えます。
prices: list[float] = [2900.0, 2925.0]ohlc: tuple[float, float, float, float] = (2900, 2950, 2880, 2925)tickers: set[str] = {"7203", "9984"}companies: dict[str, str] = {"7203": "トヨタ自動車"}タプルが「何でも入る」場合は tuple[float, ...]、辞書のキーや値が複合的なら dict[str, list[float]] のようにネストできます。
Optional と Union — 値がないかもしれない
「値があるか、なにもない(None)か」のどちらかを表すときは Optional を使います。
from typing import Optional
def find_price(ticker: str) -> Optional[float]: return None # 見つからなければ NonePython 3.10 以降は | を使った書き方が推奨されています。
def find_price(ticker: str) -> float | None: return None複数の型を許容するときも同じです。
def parse(value: str | int) -> int: return int(value)Any — 何でも受ける(最後の手段)
どうしても型を絞れないときは Any を使います。ただし Any を多用すると型ヒントの効果がなくなるため、最後の手段として扱います。
from typing import Any
def first(values: list[Any]) -> Any: return values[0]Callable — 関数を受け取る
関数を引数として受け取る関数では、Callable で型を表します。
from typing import Callable
def apply(values: list[float], func: Callable[[float], float]) -> list[float]: return [func(v) for v in values]
print(apply([1.0, 2.0, 3.0], lambda x: x * 2)) # [2.0, 4.0, 6.0]Callable[[引数の型, ...], 戻り値の型] の形で書きます。
TypedDict — 辞書のキーごとに型を決める
「特定のキーがある辞書」を表したいときは TypedDict を使います。API レスポンスや CSV の 1 行などを表すのに便利です。
from typing import TypedDict
class StockRow(TypedDict): Date: str Code: str C: int Vo: int
row: StockRow = { "Date": "2026-04-01", "Code": "7203", "C": 2900, "Vo": 11_000_000,}row["C"] のとき、エディタが型を int と認識してくれます。
dataclass の型ヒント
dataclass のフィールドはそのまま型ヒントです(#3-5「クラスの最低限」 で扱いました)。
from dataclasses import dataclass
@dataclassclass Stock: ticker: str name: str prices: list[float]
s = Stock(ticker="7203", name="トヨタ自動車", prices=[2900.0, 2925.0])データ構造を表したい場面では、TypedDict よりも dataclass のほうが扱いやすいことが多いです。
型チェッカーで検査する
型ヒントを書いただけでは実行時に検査されません。mypy や pyright といった 型チェッカー で確認します。
pip install mypymypy your_module.py型ヒントと実装の不整合を、実行前に検出できます。
def average(values: list[float]) -> float: return sum(values) / len(values)
# mypy: error: Argument 1 has incompatible type "list[str]"print(average(["a", "b"]))学習段階では必須ではありませんが、ある程度コードが育ってきたら導入する価値があります。
生成AI に読み書きしやすいコードのために
生成AI は型ヒントを 入力の手がかり として強く参照します。型ヒントを書いておくと、次のような効果があります。
- 意図が伝わる: 引数や戻り値の意味を明示でき、ブレのないコードが返りやすい
- 修正の精度が上がる: 既存コードの修正を頼んだとき、型を揃えた変更が返ってくる
- 未使用パターンが減る: 「想定外の型を渡したらどうするか」を AI が考えやすい
「型ヒントを書く前提」でプロンプトを組むと、戻ってくるコードの精度が一段上がります。
やりすぎない
型ヒントは便利ですが、書きすぎは弊害もあります。
- 複雑すぎる型 は型ヒント自体が読みづらくなる(
dict[str, list[tuple[int, str]]]など) - 小さなスクリプト に厳格な型ヒントは必須ではない
- 動的すぎる処理 は
Anyで逃げる柔軟さも必要
「ライブラリの公開関数や、データ構造の境界面に集中して書く」のが現実的な落とし所です。
生成AI へのプロンプト例
既存コードに型ヒントを付けるよう依頼する例です。
次の Python 関数に、Python 3.12 の構文で型ヒントを付けてください。
- 戻り値が None になり得る場合は str | None で明示する- リストや辞書はネストした型まで具体化する- TypedDict / dataclass を使ったほうが分かりやすい場合は提案する
def fetch_prices(ticker, start, end): if not ticker: return None return [ {"Date": "2026-04-01", "C": 2900}, {"Date": "2026-04-02", "C": 2925}, ]「使っていい記法・使ってほしくない記法」を伝えると、想定どおりの結果に近づきます(#7-2「データ分析のためのプロンプト設計」)。
まとめ
- 型ヒントは関数と変数に「期待する型」を書き添える記法
list[int]/dict[str, str]/float | Noneで多くのケースをカバーできる- 辞書の構造を表したいときは
TypedDictかdataclass - 型ヒントは生成AI への手がかりになる。書きすぎず、境界面を中心に付ける