【Python × Pyright】型チェックって何? - Pyrightの現実的な設定で、厳しすぎない型チェックを実現する
python 25 min read

【Python × Pyright】型チェックって何? - Pyrightの現実的な設定で、厳しすぎない型チェックを実現する

avatar-m-1

karrinn

著者

この記事で解決できること

  • 型チェックの基本を理解:初心者でも分かる用語解説
  • 3つの設定パターン:basic/standard/strict それぞれの使い分け
  • Pyrightで快適:VSCode統合、mypy の3-5倍高速
  • Django/Wagtail対応:現実的な設定例とトラブル回避
  • 開発速度を落とさない:実行時パフォーマンス影響なし

この記事は「Python開発環境シリーズ」の一部です

全体像を知りたい方は → Python開発、こんなことで困ってない?

あなたはこんなことで困っていませんか?

型チェックを導入したくても、厳しすぎたり、使い方が分からなかったりで諦めていませんか?

悩み1: そもそも型チェックって何?

  • 「Pythonは動的型付けなのに、型チェック?」
  • 「型ヒントって書かないといけないの?」
  • 「JSのTypeScriptは聞いたことあるけど...」
  • 「実行速度が遅くなるんじゃない?」

悩み2: 型チェッカー厳しすぎ問題

  • 「mypy入れたらエラー1000件超え...」
  • 「Django/Wagtail使ってるけど全部エラーになる」
  • 「型スタブって何?どうすれば?」
  • reportMissingImportsとか設定が複雑すぎる」

悩み3: 開発速度が落ちる問題

  • 「型ヒント書くのめんどくさい」
  • 「エラー直すのに時間かかりすぎ」
  • 「本当に効果あるの?」
  • 「型チェック通すためだけに時間が取られる」

そもそも型チェックって何?

型チェックは、コードを実行する前に型エラーを検出する仕組みです。Pythonは動的型付け言語ですが、型ヒントを追加することで静的チェックが可能になります。

型チェック(Type Checking)とは

役割:コードの型エラーを実行前に検出

  • 変数の型が間違っている
  • 関数の引数の型が違う
  • 戻り値の型が想定と異なる

重要:Pythonの型チェックは静的チェックであり、実行時には影響しません(速度低下なし)

型チェックなし(実行時エラー)

PYTHON
def add_numbers(a, b):
return a + b

result = add_numbers("5", 3)
# → "53" になる(意図しない結果)

# または
result = add_numbers(None, 3)
# → TypeError: unsupported operand type(s)

実行してみないとエラーに気づけない

型チェックあり(実行前に検出)

PYTHON
def add_numbers(a: int, b: int) -> int:
return a + b

result = add_numbers("5", 3)
# ↑ Pyrightがエラーを表示
# Error: Argument of type "str" cannot
#        be assigned to parameter "a"
#        of type "int"

実行前にエラーを発見できる

なぜ型チェックが必要?

バグの早期発見

実行前にエラーを検出。テストを書かなくても基本的な型エラーを発見できます。

ドキュメント機能

関数の入出力が明確になり、コメント不要で仕様が分かります。

リファクタリング支援

型変更時に影響範囲が自動で分かり、安全にリファクタリングできます。

IDE補完強化

より正確な補完候補が表示され、開発効率が上がります。

チーム開発での統一

型が明示されることで誤解が減り、コードレビューがスムーズになります。

実行時のパフォーマンスへの影響(重要)

型ヒントは実行時には完全に無視されるため、速度低下はありません(静的チェックのみ)。

PYTHON
# 型ヒントあり
def add(a: int, b: int) -> int:
return a + b

# 上記は実行時には以下と完全に同じ
def add(a, b):
return a + b

出典: Python typing documentation - "The Python runtime does not enforce function and variable type annotations."

基本用語の解説

型チェックを理解するために、まず基本用語を押さえましょう。

型ヒント(Type Hints)

役割:Pythonコードに型情報を追加

  • PEP 484(2014年)で導入
  • 実行時には影響なし(静的チェックのみ)
  • 標準ライブラリ typing モジュール
PYTHON
from typing import List, Dict, Optional

# 変数の型ヒント
name: str = "Alice"
age: int = 30
scores: list[int] = [85, 90, 95]  # Python 3.9+

# 関数の型ヒント
def greet(name: str) -> str:
return f"Hello, {name}!"

# Optional(値 or None)- Python 3.10+推奨記法
def find_user(user_id: int) -> str | None:
if user_id > 0:
    return "Alice"
return None

# Dictの型ヒント
def get_user_data() -> dict[str, int]:
return {"age": 30, "score": 85}

型スタブ(Type Stubs)

役割:外部ライブラリの型情報を提供

  • .pyi ファイル(型情報のみ)
  • サードパーティライブラリ用
  • django-stubs, types-requests, boto3-stubs等

なぜ必要?

PYTHON
# Djangoのコード(型ヒントなし)
from django.db import models

class User(models.Model):
name = models.CharField(max_length=100)
# ← nameの型は?Pyrightには分からない

django-stubsをインストールすると → Pyrightが「nameはstrだよ」と理解してくれる

2025年の状況

  • Django公式には型ヒントなし → django-stubs(コミュニティ製)が必要
  • Wagtailも同様に型ヒントなし
  • django-types(2025年7月リリース): django-stubsのフォーク、非mypy型チェッカー対応強化

型チェッカー(Type Checker)

役割:型ヒントをチェックするツール

ツール開発元リリース特徴
mypyCommunity2015年〜最も有名(Python製)
PyrightMicrosoft2019年〜高速(TypeScript製)
PyreMeta-大規模向け
PytypeGoogle-型推論強化
Pyrefly, ty-2025年〜新世代(Rust製、10-20倍高速)

mypy vs Pyright:どちらを選ぶべき?

2大型チェッカーの特徴を比較し、自分に合ったツールを選びましょう。

項目mypyPyright
開発元Python CommunityMicrosoft
実装言語PythonTypeScript(Node.js)
速度普通3-5倍速い
VSCode統合手動設定必要Pylance拡張(標準)
リアルタイムチェック弱い強い(保存時即座)
Django対応プラグイン必要設定で対応可
学習コスト高い(設定複雑)中(設定シンプル)
エコシステム成熟成長中
アーキテクチャ伝統的マルチパス遅延評価(JIT)

Pyrightのメリット

  • mypy の 3-5倍高速(大規模プロジェクトで顕著)
  • VSCodeで標準(Pylance経由)
  • リアルタイムチェック(保存時即座)
  • 段階的な厳しさ設定(off/basic/standard/strict)
  • pyproject.toml で一元管理
  • インテリジェントな型推論
  • ウォッチモード、並列処理対応

Pyrightのデメリット

  • mypy より新しい(エコシステム未成熟)
  • Node.js必要(VSCode以外で使う場合)
  • 一部の高度な mypy 機能が未対応
  • 日本語情報が mypy より少ない

どちらを選ぶべき?

  • VSCode使ってるPyright推奨(統合が楽、高速)
  • 既にmypy使用中 → mypy継続(無理に変えなくてOK)
  • これから始めるPyright推奨(速くて楽)

Pyright導入手順:10分で終わる

VSCode、pyproject.toml、VSCode設定の3ステップで完了します。

Step 1: VSCode拡張インストール(1分)

  1. VSCode を開く
  2. 拡張機能を検索: Pylance
  3. インストール

Pyrightが自動的に有効化されます

Pylance = Pyright + VSCode統合機能
Pylanceは、Pyrightエンジンに加えて、オートコンプリート、コードナビゲーション、インラインエラー表示などの機能を提供します。

Step 2: 基本設定(3分)

設定のポイント

pyproject.toml にPyrightの基本設定を追加します。Pythonバージョン、型チェックモード、仮想環境パス、対象ディレクトリを指定することで、プロジェクト全体の型チェックを有効化できます。

  • pythonVersion: 使用するPythonバージョン
  • typeCheckingMode: 型チェックの厳しさ(basic推奨)
  • venvPath, venv: 仮想環境の場所
  • include: チェック対象ディレクトリ
  • exclude: 除外するディレクトリ(migrations等)

3つの設定パターン

  • basic: 基本的なエラーのみ、型ヒントがない関数も許容
  • standard: より厳密なチェック、型ヒント推奨
  • strict: 最も厳密、全ての関数に型ヒント必須
pyproject.toml
[tool.pyright]
# Pythonバージョン
pythonVersion = "3.11"

# 型チェックの厳しさ(off/basic/standard/strict)
typeCheckingMode = "basic"  # 最初は basic がおすすめ

# 仮想環境のパス
venvPath = "."
venv = ".venv"

# チェック対象
include = ["myproject"]

# 除外対象
exclude = [
"**/node_modules",
"**/__pycache__",
"**/migrations",  # Djangoマイグレーション除外
]

Step 3: VSCode設定(3分)

VSCode統合の設定

.vscode/settings.json に設定を追加することで、VSCode上でリアルタイムに型チェックが動作します。エラーの厳しさを調整し、開発体験を最適化できます。

  • typeCheckingMode: pyproject.tomlと同じ設定
  • autoImportCompletions: 自動インポート補完
  • diagnosticSeverityOverrides: エラーの厳しさ調整

これで保存時に自動型チェック!

.vscode/settings.json
{
"python.analysis.typeCheckingMode": "basic",
"python.analysis.autoImportCompletions": true,
"python.analysis.diagnosticSeverityOverrides": {
"reportGeneralTypeIssues": "warning",  // エラーではなく警告
"reportOptionalMemberAccess": "none"   // Optional系は無視
}
}

悩み別の解決策

3つの悩みそれぞれに対する具体的な解決方法を紹介します。

悩み1解決: 型ヒントの書き方

基本の型ヒント

型ヒントの基本構文

Pythonの型ヒントは、関数の引数と戻り値に型情報を付与します。Python 3.9以降では、組み込み型(list, dict)を直接使えます。

  • int, str: 基本型
  • list[int]: 型付きリスト(Python 3.9+)
  • dict[str, str]: 型付き辞書
  • str | None: Optional型(Python 3.10+)
  • str | int: Union型(Python 3.10+)
type_hints_basic.py
# 基本型
def calculate_age(birth_year: int) -> int:
return 2025 - birth_year

# リスト(Python 3.9+)
def get_scores() -> list[int]:
return [85, 90, 95]

# 辞書
def get_user() -> dict[str, str]:
return {"name": "Alice", "email": "alice@example.com"}

# Optional(値 or None)- Python 3.10+推奨
def find_user(user_id: int) -> str | None:
if user_id > 0:
    return "Alice"
return None

# Union型(Python 3.10+推奨記法)
def process_data(value: str | int) -> str:
return str(value)

Python 3.10以降の新記法(PEP 604)

新記法の利点

Python 3.10以降では、|演算子を使った簡潔な型表記が可能になりました。typingモジュールのインポートが不要で、コードがシンプルになります。

  • Union[str, int]str | int
  • Optional[str]str | None
  • typingモジュールのインポート不要
type_hints_modern.py
# 古い書き方(非推奨)
from typing import Union, Optional

def old_style(value: Union[str, int]) -> Optional[str]:
return str(value) if value else None

# 新しい書き方(推奨)
def new_style(value: str | int) -> str | None:
return str(value) if value else None

Django/Wagtailの型ヒント

フレームワーク固有の型

Django/Wagtailには専用の型が用意されています。django-stubsをインストールすることで、Pyrightがこれらの型を理解できます。

  • HttpRequest, HttpResponse: Djangoのリクエスト/レスポンス
  • Page: Wagtailのページモデル

出典: PEP 604 – Complementing PEP 484

django_wagtail_hints.py
from django.http import HttpRequest, HttpResponse
from wagtail.models import Page

# Viewの型ヒント
def my_view(request: HttpRequest) -> HttpResponse:
return HttpResponse("Hello")

# Wagtail Page
def get_page_title(page: Page) -> str:
return page.title

悩み2解決: Django/Wagtail対応設定(現実的な設定例)

問題:Django/Wagtailは型ヒントがない

PYTHON
# Djangoのコード
from django.contrib.auth.models import User

# Pyrightが型を理解できない...
user = User.objects.get(id=1)
print(user.username)  # ← 型不明

→ エラーが大量に出てしまう

解決策1: 型スタブをインストール

型スタブの役割

django-stubsは、Djangoのための型情報を提供するパッケージです。これをインストールすることで、Pyrightが Django のクラスやメソッドの型を理解できるようになります。

  • django-stubs: Djangoの型情報
  • types-*: サードパーティライブラリの型情報
bash
# django-stubsをインストール
uv add --dev django-stubs types-requests

# これでPyrightがDjangoの型を理解してくれる

解決策2: 現実的な pyproject.toml 設定

Django/Wagtail向けの設定

Wagtailプロジェクトから引用した現実的な設定例です。reportMissingImports = false などの緩和設定により、Django/Wagtailでも快適に型チェックを利用できます。

  • typeCheckingMode = "basic": 現実的な厳しさ
  • reportMissingImports = false: importエラー無視
  • reportOptionalCall = false: Optional系エラー緩和
  • migrations等を除外

ポイント

  • typeCheckingMode = "basic" が現実的
  • reportMissingImports = false でDjango/Wagtailのimportエラー回避
  • reportOptionalCall = false で Optional 系のエラー減らす
pyproject.toml
[tool.pyright]
pythonVersion = "3.11"
typeCheckingMode = "basic"  # basicが現実的
venvPath = "."
venv = ".venv"
include = ["wagtail_template"]
exclude = [
"**/node_modules",
"**/__pycache__",
"**/migrations",
"**/venv",
]

# Django/Wagtailでの現実的な設定(重要!)
reportArgumentType = false          # 引数型チェック緩和
reportAssignmentType = false        # 代入型チェック緩和
reportOptionalCall = false          # Optional系チェック無効
reportMissingImports = false        # importエラー無視

# 上記設定で、Django/Wagtailでも快適に使える

依存関係の設定

必要な型スタブパッケージ

pyproject.tomlの[dependency-groups]セクションに、開発時に必要な型スタブパッケージを列挙します。主要なライブラリの型情報を網羅することで、より正確な型チェックが可能になります。

  • Django関連: django-stubs
  • AWS: boto3-stubs
  • データ処理: pandas-stubs
  • その他: types-* パッケージ

出典: Using Typed Python in Large Django Projects

pyproject.toml
[dependency-groups]
dev = [
"pyright>=1.1.402",
"django-stubs>=5.2.0",
"types-requests>=2.32.0.20250602",
"boto3-stubs>=1.38.30",
"celery-types>=0.23.0",
"pandas-stubs>=2.2.3.250527",
"types-redis>=4.6.0.20241004",
"types-psycopg2>=2.9.21.20250516",
"types-pillow>=10.2.0.20240822",
]

悩み3解決: 開発速度を落とさない工夫

3つの設定パターンから選ぶ

プロジェクトに合わせた設定

typeCheckingModeは、プロジェクトの規模や型安全性の要求に応じて選択できます。いつでも変更可能なので、まずは緩めのbasicから始めるのが現実的です。

  • basic: 基本的なエラーのみ、型ヒントがない関数も許容
  • standard: より厳密なチェック、型ヒント推奨
  • strict: 最も厳密、全ての関数に型ヒント必須

ポイント:型チェックは「助け」であって「足かせ」ではありません。プロジェクトに合った設定を選びましょう。

pyproject.toml
# パターン1: 緩め(型チェックに慣れたい)
[tool.pyright]
typeCheckingMode = "basic"

# パターン2: 標準(バランス重視)
[tool.pyright]
typeCheckingMode = "standard"

# パターン3: 厳格(型安全性重視)
[tool.pyright]
typeCheckingMode = "strict"

特定ファイル・行を除外

柔軟な除外設定

型チェックを一時的に無効化したい場合、コメントで除外指定ができます。レガシーコードや複雑なロジックに対して有効です。

  • # pyright: ignore: ファイル全体を除外
  • # pyright: ignore (行末): 特定行のみ除外
  • # type: ignore[...]: 特定のエラーのみ無視
example.py
# ファイル全体を除外
# pyright: ignore

# 特定行のみ除外
result = some_complex_function()  # pyright: ignore

# 特定のエラーのみ無視
# type: ignore[reportGeneralTypeIssues]

CI/CDでの型チェック

自動化の重要性

CI/CDパイプラインに型チェックを組み込むことで、マージ前に型エラーを検出できます。コードレビューの負担を軽減し、品質を保証します。

  • プルリクエスト時に自動実行
  • 型エラーがあればマージをブロック
  • uvと組み合わせて高速実行
.github/workflows/ci.yml
# .github/workflows/ci.yml
- name: Type check
run: uv run pyright

型チェックフロー図

Pyright導入後の開発フローを可視化します。

開発フロー(Pyright導入後)

FLOW
1. コード編集
↓
2. 型ヒント追加
def greet(name: str) -> str:
↓
3. ファイル保存
↓(Pylanceが自動実行)
4. Pyrightが型チェック(即座、0.5秒以内)
↓(型エラーがあれば)
5. VSCode上に赤い波線表示
↓
6. エラーにマウスオーバー
↓
7. エラー内容確認
"Argument of type 'int' cannot be assigned
to parameter 'name' of type 'str'"
↓
8. 修正
↓
9. 保存 → 再チェック → OK!

→ 実行前にバグ発見!

よくあるトラブルシューティング

Pyright導入時によくある問題と解決策をまとめました。

Pylanceが動かない

JSON
// .vscode/settings.json
{
"python.languageServer": "Pylance",
"python.analysis.typeCheckingMode": "basic"
}

VSCode設定で明示的にPylanceを指定します。

型スタブが見つからない

BASH
# 型スタブをインストール
uv add --dev django-stubs types-requests

# または手動でpyproject.tomlに追加
[dependency-groups]
dev = [
"django-stubs>=5.2.0",
"types-requests>=2.32.0",
]

型スタブパッケージをインストールして型情報を提供します。

エラーが多すぎる場合

TOML
[tool.pyright]
# 緩めの設定を選ぶ
typeCheckingMode = "basic"

# または一時的に無効化
# typeCheckingMode = "off"

設定パターンを見直して、プロジェクトに合ったものを選びます。

useLibraryCodeForTypes問題

TOML
# Wagtail/Django非型付けライブラリでの推論を無効化
[tool.pyright]
useLibraryCodeForTypes = false

出典: Advice on using Wagtail with Pylance

Pythonの型システムの歴史

Pythonの型システムは、2014年のPEP 484承認から急速に発展してきました。

型システムの進化

  • 2006年: MyPy開発開始(Jukka Lehtosalo氏)
  • 2014年: PEP 484承認(型ヒント標準化)
  • 2015年: Python 3.5で型ヒント導入、mypy 0.1リリース
  • 2016年: typing モジュール追加
  • 2019年: Pyright発表(Microsoft)
  • 2020年: Pylance発表(VSCode拡張)、PEP 585(list[int]記法)
  • 2021年: Python 3.10でUnion型の | 記法導入(PEP 604)
  • 2022年: Python 3.11でSelf, TypeVarTuple追加
  • 2023年: Pyright急成長(VSCodeデフォルト)
  • 2024年: Python 3.12でtype文導入
  • 2025年: Python 3.13で型システム強化、Rustベース型チェッカー(Pyrefly, ty)登場

なぜPyrightが選ばれる?

  • VSCode標準(Pylance)
  • mypy の 3-5倍高速
  • リアルタイムチェック
  • 設定がシンプル

パフォーマンス比較

Pyrightは、mypyと比較して3-5倍高速に動作します。大規模プロジェクトほど差が顕著です。

型チェック実行時間の比較(Djangoプロジェクト 5万行)

Pyrightアーキテクチャの優位性

遅延評価(Lazy Evaluation)

必要な部分だけ型評価し、無駄な処理を省きます。

インクリメンタル更新

変更箇所のみ再評価し、全体の再チェックを避けます。

並列処理

マルチコアCPUを活用して高速化します。

メモリ効率

大規模コードベースでもメモリ消費を抑えます。

重要:型ヒント自体は実行時のパフォーマンスに影響しません(静的チェックのみ)。

CI/CDでの使用例

GitHub Actionsでの型チェック自動化の例を紹介します。

GitHub Actions設定例

CI/CDパイプラインへの統合

GitHub Actionsを使って、プルリクエストやpush時に自動的に型チェックを実行します。uvを使うことで、依存関係のインストールと型チェックが高速に完了します。

  • push/pull_request時に自動実行
  • uvで依存関係を高速インストール
  • pyrightで型チェックを実行
  • エラーがあればCI失敗

ポイント

  • CI/CDで型チェック必須化
  • 開発時はVSCodeで快適に
  • マージ前に必ずチェック
.github/workflows/ci.yml
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
type-check:
runs-on: ubuntu-latest
steps:
    - uses: actions/checkout@v4

    - name: Install uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

    - name: Setup Python & install dependencies
    run: |
        uv sync

    - name: Run Pyright
    run: |
        uv run pyright

型ヒントのベストプラクティス

効果的な型ヒントの書き方を学びましょう。

悪い例:曖昧な型

PYTHON
def process(data: list) -> list:  # 曖昧
return data

何のリストか分からない

良い例:明確な型

PYTHON
def process(data: list[str]) -> list[int]:  # 明確
return [len(s) for s in data]

入力も出力も明確

Optionalの使い方(Python 3.10+推奨記法)

新記法の利点

Python 3.10以降では、str | Noneの記法が推奨されます。typing.Optionalよりも直感的で、コードが簡潔になります。

  • str | None: 推奨される記法
  • Optional[str]: 旧記法(非推奨)
  • typingモジュールのインポート不要
optional_example.py
# Python 3.10以降は | None 推奨
def find_user(user_id: int) -> str | None:
if user_id > 0:
    return "Alice"
return None

# 古い書き方(非推奨)
from typing import Optional
def find_user(user_id: int) -> Optional[str]:
...

型エイリアス

複雑な型の簡略化

型エイリアスを使うことで、複雑な型定義を再利用可能な名前で表現できます。コードの可読性が向上し、型の変更も一箇所で済みます。

  • 複雑な型に分かりやすい名前を付ける
  • 型の変更が一箇所で済む
  • コードの可読性が向上
type_alias.py
# 複雑な型は別名をつける
UserDict = dict[str, str | int]

def get_user() -> UserDict:
return {"name": "Alice", "age": 30}

公開APIに型ヒントを付ける

選択的な型ヒント

すべての関数に型ヒントを付ける必要はありません。公開API(外部から呼ばれる関数)に型ヒントを付けることで、インターフェースが明確になります。内部関数は省略可能です。

  • 公開APIには必ず型ヒントを付ける
  • 内部関数(_で始まる)は省略可能
  • インターフェースの明確化が目的

出典: Typing Best Practices

public_api.py
# 公開APIには型ヒント
def public_api(data: str) -> dict[str, str]:
return _internal_process(data)

# 内部関数は任意
def _internal_process(data):
return {"result": data}

よくある質問(FAQ)

型チェックに関するよくある疑問にお答えします。

A: VSCode使うならPyright推奨。高速でリアルタイムチェック。既にmypy使用中なら無理に変えなくてOK。

A: 不要。公開APIや複雑な関数から始めればOK。段階的に追加していく。

A: 使えます。django-stubsインストール + 設定緩和で快適。reportMissingImports = falseが重要。

A: 遅くなりません。型ヒントは実行時には完全に無視されます(静的チェックのみ)。

A: 最小限ならOK。ただし理由をコメントで書く。乱用は避ける。

A: Pyrefly, tyが登場。10-20倍高速だが、まだ実験段階。Pyrightが現時点で最も実用的。出典: Comparing Python's New Rust-Based Type Checkers

参考文献・関連リンク

より詳しく学びたい方のための公式ドキュメント・解説記事をご紹介します。

他の記事を読む

型チェックの導入が完了したら、他のPython開発ツールも確認しましょう。

依存関係管理

Python環境管理はuvが最高 - おすすめのPython環境管理

pip、pyenv、poetry...もう全部uvでよくない?

記事を読む

コード品質・自動化

コード整形、手動でやってない? - ruff + pre-commitで忘れない仕組みを作る

コード整形、手動でやってない? - ruff + pre-commit

記事を読む

全体像を見る

Pythonプロジェクトの長期運用で本当に必要なこと - 環境・品質・型の3本柱

Python開発、こんなことで困ってない?

記事を読む

サンプルリポジトリ

Pyright + django-stubsの実際の設定を公開しています。そのままコピーして使えます。

GitHubで見る

関連トピック

コメント (0)

まだコメントはありません。最初のコメントを残しませんか?

コメントを投稿

メールアドレスが公開されることはありません。必須項目には * が付いています