python-typing について
Python パッケージに静的型チェックを導入するスキルです。新規プロジェクトやレガシーコードを扱うチーム向けに、チェッカーの選定、固定バージョンでの設定、段階的な厳格化、エラー対応、配布物内の型情報マーカーの検証を案内します。
主な機能
- 01主要な型チェッカーを一つ選定
- 02チェッカーを固定し pyproject.toml を設定
- 03例外を管理しながら段階的に厳格化
- 04型エラーと抑制コメントの対応
- 05ビルド成果物内の py.typed を検証
活用シーン
- 01新しい Python パッケージに型チェックを導入
- 02レガシーコードへ段階的にチェックを追加
- 03下流利用者向けにライブラリの型注釈を配布
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ paldom/ python-skills --skill python-typingインストール後、Claude Code で/python-typingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/evals.jsonreferences/checker-selection.mdpy-typed-distribution.mdstrictness-ratchet.mdscripts/check_py_typed.py詳細
Python の型付け
チームが根拠を示せる厳格さの方針で、ユーザーの Python パッケージに静的型チェックを導入します。チェッカーは1つに絞ってバージョンを固定し、pyproject.toml で設定し、モジュールごとの例外設定は負債として追跡し、段階的に厳格化します。また、ライブラリの場合は、ビルドした wheel に py.typed マーカーが確実に含まれることを検証します。さらに、チェッカーが報告するエラーの修正方法も扱います。
使用しない場合
- Ruff の lint または format の失敗。型注釈スタイルに関する ANN ルールも含みます。これらは型チェックではなく lint です(インストールされている場合は python-lint スキルを使用してください)。
- テストスイートまたは pytest のセットアップの失敗(python-testing)。
- 実行時の例外。実行時に発生した
TypeErrorは、チェッカーの設定作業ではなく、バグとして直接デバッグしてください。 - チェッカーを実行する CI ワークフローの YAML(python-ci)、または pre-commit の設定(python-precommit)。このスキルで動作するコマンドを、それらに引き継ぎます。
py.typedマーカーそのものを除く、パッケージのメタデータ、ビルドバックエンド、wheel のビルド(python-packaging)。
ワークフロー
1. 選択する前に調査する
- レイアウト:
src/かフラットか、インポートするパッケージ名、ライブラリ(公開済みで利用者がいる)かアプリケーションか。 requires-pythonで指定された最低サポート Python バージョン。チェッカーは、実行中のインタープリターではなく、このバージョンを対象にする必要があります。- チェッカーの プラグイン が必要なフレームワーク依存関係:
grep -E "django|sqlalchemy|pydantic" pyproject.toml。プラグインがあるのは mypy のみです。これにより、チェッカーの選択が決まることがあります。 - 既存の設定(
[tool.mypy]、[tool.pyright]、mypy.ini、pyrightconfig.json)。黙って置き換えず、既存の設定を拡張してください。 - 新規プロジェクトかレガシーコードベースか(おおよその型注釈の網羅率)。これにより、ステップ4で最初から厳格にするか、段階的に厳格化するかが決まります。
2. チェッカーを1つ選ぶ — 競争の行方はまだ決まっていません
型チェッカーの分野では、現在も競争が続いており、決着していません(mypy、pyright/basedpyright、ty、Pyrefly、zuban)。どれかを明らかな勝者として紹介せず、速度倍率や適合率も引用しないでください。出回っている数値は単一の情報源に基づき、一部は反証されています。妥当な選択基準は次のとおりです。
| 状況 | 選択 |
|---|---|
| Django(django-stubs)または Pydantic プラグインに依存するスタック | mypy + フレームワークのプラグイン(SQLAlchemy 2.x はネイティブで型付けされています。mypy プラグインは非推奨で、mypy 1.10 で更新が停止しました) |
| プラグインが不要な新規プロジェクトで、チームが VS Code を使用 | pyright(standard、次に strict) |
| VS Code 以外のエディター(Neovim、Helix、Cursor)を使用する場合、またはより厳しいデフォルト設定が必要な場合 | basedpyright |
| uv/Ruff を使い、ベータ版の頻繁な変更を許容できる場合 | ty をローカルで試験導入し、CI ゲートには mypy または pyright を維持 |
| 数百万行規模のモノレポ | Pyrefly を評価 |
CI ゲートとして使うプライマリチェッカーは1つに決めてください。 エディターで pyright(Pylance)を使い、CI では別のチェッカーを使うのは一般的です。一方、2つのチェッカーを ゲートとして 実行すると、抑制コメントを並行して管理する必要があります(注意点5)。詳細とトレードオフについては、references/checker-selection.md を参照してください。
3. バージョンを固定してインストールし、uv で実行する
バージョンを正確に固定してください。チェッカーのリリースでは新しい診断が定期的に追加されるため、バージョンを固定しないと、無関係な PR によって CI が失敗します。以下の固定バージョンは、PyPI にある最新リリースに置き換えてください。
uv add --dev "mypy==2.3.1" # or: "pyright==1.1.413" (PyPI wrapper, bundles node)
uv run mypy src tests # or: uv run pyright
uv を使わない場合(参考用、1回限り):python -m pip install "mypy==2.3.1" を実行してから、python -m mypy src tests を実行します。依存関係に手を加えずに ty を試験導入する場合は、uvx --from "ty==0.0.80" ty check src を実行してください(こちらも最新の固定バージョンに置き換えてください。ty はまだ 1.0 より前のバージョンです)。
4. pyproject.toml で設定する
mypy と pyright は異なるテーブルを参照するため、移行中に両方を共存させられます。mypy の場合、strict = true によって、型注釈のないコードも mypy のチェック対象になります(注意点1)。
[tool.mypy]
python_version = "3.10" # lowest supported, from requires-python
strict = true
warn_unused_ignores = true
# plugins = ["pydantic.mypy"] # only if pydantic is a dependency
[[tool.mypy.overrides]]
module = ["some_untyped_lib.*"] # third-party deps that ship no types
ignore_missing_imports = true
pyright / basedpyright の場合(フォークでは [tool.basedpyright] を使用してください):
[tool.pyright]
include = ["src", "tests"]
exclude = ["**/legacy"] # added on top of pyright's defaults (node_modules, __pycache__, .*)
typeCheckingMode = "standard" # "strict" for new projects
pythonVersion = "3.10"
ty は pyproject.toml の [tool.ty](または ty.toml)を読み込みます。設定項目は少なく、ベータ版で変更される可能性があるため、古い例をそのまま信頼せず、uv run ty --help を確認してください。
5. 厳格さの設定 — 初日から厳格にするか、段階的に引き上げます。後から一斉に適用してはいけません
- 新規プロジェクト:最初のコミットから
strict = true/typeCheckingMode = "strict"にします。厳格さを後から適用すると、コントリビューターに負担がかかり、エラーが大量に発生します。 - レガシーコードベース:段階的に引き上げます。グローバルでは厳格にしつつ、モジュールごとの例外を設け、例外は減らす一方にします。
[tool.mypy]
strict = true
[[tool.mypy.overrides]]
module = ["myapp.legacy.*"] # exempt, migrate module-by-module
ignore_errors = true
pyright では、同等の設定として standard をベースに、厳格にチェックする範囲を指定する strict = ["src/myapp/core"] 配列を使います。両方のチェッカーにおける段階的な完全適用については、references/strictness-ratchet.md を参照してください。
- チームが確認できる場所(CONTRIBUTING または README)に方針を記録します。選択したチェッカー、実行コマンド、例外は減らす一方にするというルールを記載してください。
6. py.typed を同梱し、wheel を検証します(ライブラリ)
py.typed マーカーがない場合、PEP 561 により、チェッカーはライブラリからのすべてのインポートを Any として扱います。ソースには型注釈があっても、利用者にはひそかに見えない状態になります。
touch src/<pkg>/py.typed
ビルドバックエンドによって、.py 以外のファイルをパッケージに含めるかどうかは異なります(setuptools では [tool.setuptools.package-data] が必要ですが、hatchling では通常含まれます)。そのため、ソースツリーを信用せず、アーティファクトを検証してください。
uv build
python3 "${CLAUDE_SKILL_DIR}/scripts/check_py_typed.py" --package <pkg>
このスクリプトは、ソースパッケージ、最新の wheel、または最新の sdist のいずれかに py.typed が含まれていない場合、ゼロ以外の値で終了します。バックエンドごとの設定とスタブ配布の選択肢については、references/py-typed-distribution.md を参照してください。
7. 報告されたエラーを修正します
次の順にトリアージします。
- まず実際のバグを修正します —
Optionalの誤用、戻り値の型の誤り、到達不能な分岐などです。これらこそ型チェックの成果なので、抑制しないでください。 - 型付けされていないサードパーティーのインポート —
types-*のスタブパッケージが存在する場合はインストールし、バージョンを固定します(スタブのバージョンはライブラリとは別に管理します)。それでもだめな場合に限り、モジュール単位のignore_missing_importsオーバーライドを使います。グローバルフラグは使わないでください。 - 実際に誤検出されたエラー — エラーコードを指定したコメントで抑制します。mypy では
# type: ignore[arg-type]、pyright では# pyright: ignore[reportArgumentType]を使い、古くなった抑制コメントでビルドが失敗するように、warn_unused_ignores(mypy)/reportUnnecessaryTypeIgnoreComment(pyright)を有効にしておきます。 - グローバル設定を緩めてエラーを解決してはいけません。
8. 引き継ぎます
型チェックコマンドが契約となります。python-ci スキル(インストール済みの場合)がこれを CI ジョブにし、python-precommit がフックに組み込みます。これはこのスキルの役割ではありません。ローカルでコマンドが通るところまでで終了してください。
出力仕様
以下をすべて満たせば完了です。
- プライマリチェッカーがちょうど 1 つで、開発依存関係にバージョンを固定して追加され、
pyproject.tomlで設定されている。 uv run <checker> ...がsrc(および、理由を明記して意図的に除外していない限りtests)に対して終了コード 0 で終了する。- 厳格さに関する方針が記録されている。厳格にするか、現在の段階と負債として追跡する例外リストを記録する。
- ライブラリの場合:
py.typedがパッケージに含まれ、さらに新しくビルドした wheel に対してscripts/check_py_typed.pyが成功する。 - すべての抑制コメントでエラーコードが指定されており、未使用の抑制の検出が有効になっている。
- チームが確認できる場所に実行コマンドが記載されている。
失敗しやすい点と注意事項
- mypy がエラーなしでも、チェック済みとは限りません。 デフォルトでは mypy は型注釈のない関数本体をスキップするため、「エラーなし」の実行でも、コードベースの大半が無視されている可能性があります。エラーなしの実行結果を信頼する前に、
check_untyped_defs = true(またはstrict)を設定してください。 - 全体への strict 設定とモジュールごとの緩和は両立しません。 どちらのツールにも長年の問題(mypy #11401、pyright #601)があり、モジュールごとに strict ルールをきれいに緩和することはできません。うまくいく方法は、全体に strict を設定してモジュールごとに
ignore_errors(mypy)を使うか、standardをベースに、strict にするディレクトリを配列で指定する方法(pyright)です。 - pyright は mypy よりレガシーコードで多くのエラーを出します。 もともと型注釈のないコードもチェックしているため、いきなり
strictにすると一度に大量のエラーが見つかります。既存のコードベースでは、まずstandardから始めてください。 - ホイールに
py.typedが含まれていないのは、典型的な見えにくい失敗です。マーカーファイルが git にはあるのに、バックエンドが成果物から除外してしまい、下流のユーザーには気付かれないままAnyが渡されます。ソースツリーではなく、ビルドしたホイールを必ず確認してください(手順 6)。 - チェッカーが 2 つあると、抑制も 2 種類必要です。 チェッカーの判定は一致しないため(kwargs の型付け、
__new__の型推論、ユニオン型の拡張など)、同じ行で# type: ignore[...]と# pyright: ignore[...]の両方が必要になることがあります。このコストを承知のうえで受け入れるか、ゲートを 1 つにしてください。 - strict の設定は互換性がありません。 mypy の strict、pyright の strict、basedpyright の「recommended」プリセット、ty/Pyrefly のルールは、それぞれ異なる契約です。あるチェッカーでエラーがゼロでも、ほかのチェッカーについては何も保証されません。
- Pydantic との摩擦。 チェッカーは
before/wrapバリデーターの内部を確認できないため、検証前の入力型を使ってコンストラクターを呼び出すと、誤検知が発生します。トレードオフのある選択肢として、mypy とpydantic.mypyプラグインの併用、モデルモジュールに限定したルールの抑制、または(最先端の選択肢として)Pyrefly の実験的な Pydantic 統合があります。別の注意点として、静的解析で問題のないモデルでも、実行時の安全性が保証されるわけではありません。Pydantic は独自の strict モードを有効にしない限り、デフォルトで値を強制変換します("30"は30になります)。 - ty/Pyrefly の成熟度。 プラグインシステムがないため(Django/SQLAlchemy/Pydantic のプラグインスタックは移行できません)、ベータ版相当の仕様変更が頻繁にあり、pyright から移行すると、以前は検出できていた診断を見逃す可能性があります。ty の「段階的保証」(注釈の削除や緩和によって新たなエラーが発生することはなく、精度を上げると実際の問題が見つかる場合がある)により、段階的な試験導入には適しています。ただし、エディターやローカルで使うツールとしては適していますが、OSS パッケージの CI ゲートとして使うには時期尚早です。
- pyright の
excludeは追加指定です。 カスタム項目はデフォルト(**/node_modules、**/__pycache__、**/.*)に追加され、デフォルトが優先されます。そのため、includeに指定してもドットディレクトリを除外対象から外せません。代わりにコードを移動してください。 - Ruff は型チェッカーではありません。 Ruff の ANN ルールは型注釈のスタイルをチェックするもので、型エラーは一切検出しません。lint が通っても、型については何もわかりません。
- チェッカーのアップグレードでデフォルト設定が変わります。 mypy 2.0(2026-05)では、
--local-partial-typesと--strict-bytesがデフォルトで有効になり、--allow-redefinitionのセマンティクスが変更され、--python-version 3.9が削除され、実験的な並列チェック(--num-workers N)が追加されました。通常のバージョンアップでも CI が新たに失敗する可能性があります。そのため、手順 3 ではバージョンを正確に固定し、計画的にアップグレードします。
同梱リソース
- references/checker-selection.md — 有力候補の概要、比較表、選定ガイド、エディターと CI を組み合わせるパターン。
- references/strictness-ratchet.md — mypy と pyright の完全な設定例を含む、段階的な strict モードの導入。
- references/py-typed-distribution.md — PEP 561 の配布方法、バックエンドごとのパッケージ設定、検証方法。
scripts/check_py_typed.py— ソースパッケージとビルド済みの wheel/sdist 成果物内にpy.typedがあることを確認します。読み取り専用で、失敗時はゼロ以外の終了コードを返します。