TL

型システム(静的型付け vs 動的型付け)

値の「型」をいつ・どこまで検査するかのルール。コンパイル時に守るか実行時に確かめるかで、安全性と書きやすさが変わる。

中級型システム言語パラダイム最終更新: 2026-06-04
TL;DR要点だけ先に
  • 1.型システムは「この値で何ができるか」を決めるルール。検査のタイミングで静的(コンパイル時)と動的(実行時)に分かれる。
  • 2.静的=早期にバグ発見・補完が効く、動的=書き出しが速く柔軟。トレードオフであり優劣ではない。
  • 3.「静的か動的か(いつ検査)」と「強いか弱いか(暗黙変換を許すか)」は別の軸。混同しやすい。

型は何を守ってくれる?

「型」とは、値の種類と、その値に許される操作のセットです。number 同士は足し算・引き算ができ、string は連結や長さ取得ができる、という具合に。型システムは、

  • 不正な操作を弾く(数値を関数として呼ぶ、存在しないプロパティを読む など)
  • 意図を記録する(この引数は文字列を受け取る、という契約がコードに残る)
  • 最適化やツール支援の土台になる(補完・リファクタリング・高速化)

ここで重要なのが「いつ検査するか」。これが静的/動的を分ける軸です。

静的型付け vs 動的型付け(いつ検査するか)

  • 静的型付け: **実行する前(コンパイル時)**に型を検査する。型が合わなければそもそも動かせない。例: Java, TypeScript, Go, Rust, C#
  • 動的型付け: 実行している最中に、値を触ったその瞬間に型を確かめる。間違っていればその行でエラー。例: Python, JavaScript, Ruby, PHP

同じ「文字列を数値で割る」バグでも、見つかるタイミングがまるで違います。

// TypeScript(静的): 実行する前にエディタ/コンパイラが赤線
function half(n: number) {
  return n / 2;
}
half("10"); // ❌ コンパイルエラー: string は number に渡せない
# Python(動的): 動かしてその行に到達して初めて落ちる
def half(n):
    return n / 2

half("10")  # ❌ 実行時に TypeError(その関数が呼ばれるまで気づけない)
観点静的型付け動的型付け
検査の時点コンパイル時(実行前)実行時(その行に来た時)
バグ発見早い・網羅的テストや本番で初めて表面化
エディタ補完効きやすい(型が分かる)効きにくい(実行しないと不明)
書き出しの速さ型注釈の分やや重い軽い・試行錯誤が速い
代表言語Java / TypeScript / Go / RustPython / JavaScript / Ruby

強い型付け vs 弱い型付け(暗黙変換を許すか)

ここでよくある誤解。「静的=強い、動的=弱い」ではありません。“いつ検査するか”(静的/動的)と、“勝手に型を変換するか”(強い/弱い)は別の軸です。

  • 強い型付け: 型が違えば勝手に変換しない1 + "2" をエラーにするか、明示変換を要求する。
  • 弱い型付け: 文脈に合わせて暗黙に変換する1 + "2""12" になったりする。

Python は動的だが強い型付けで、1 + "2" は実行時にエラーになります。一方 JavaScript は動的かつ弱いため、暗黙変換が走ります。

# Python(動的・強い): 暗黙変換しないのでエラー
1 + "2"   # ❌ TypeError: int と str は足せない
// JavaScript(動的・弱い): 暗黙変換で“それっぽく”動いてしまう
1 + "2"    // "12"  (数値が文字列化されて連結)
"5" - 1    // 4     (今度は文字列が数値化されて引き算)
[] + {}    // "[object Object]"
“動的”と“弱い”を一緒くたにしない

よく「JavaScript は型がゆるい」と言われますが、これは動的(実行時検査)であること弱い(暗黙変換)であることの二重の意味が混ざった表現です。Python も動的ですが強いので、"5" - 1 は黙って通らずエラーになります。この2軸を分けて考えると、言語ごとの“クセ”がきれいに整理できます。

型推論:書かなくても型は付く

「静的型付け=型注釈を毎回書く」も誤解です。多くの静的言語は型推論を備え、初期値などから型を自動で割り出します。明示注釈を減らしつつ、静的検査の恩恵は受けられる、というおいしいとこ取り。

let count = 0;        // : number と書かなくても number と推論される
let name = "Tech";    // string と推論
count = "x";          // ❌ それでも型違反は弾かれる

つまり「静的か動的か」と「注釈を書くか書かないか」も、本当は別の話。推論が強力な Rust や TypeScript では、注釈は要所だけで済みます。

それぞれの利点・欠点

静的型付けの強み動的型付けの強み
開発初期設計が型に現れ、契約が明確とにかく速く形にできる
大規模・長期リファクタが安全・自己文書化small & 短命なら身軽でよい
バグ型由来のミスを実行前に一掃型以外のテストに集中できる
弱点ボイラープレート・学習コスト実行するまで型エラーが潜む
“両取り”の現実解:漸進的型付け

TypeScript(JS に型を後付け)や Python の型ヒント+mypy のように、動的言語に静的検査を“あとから少しずつ”足すアプローチ(漸進的型付け/gradual typing)が今の主流です。「最初は動的で素早く、育ったら型を入れて固める」が現実的な戦い方。any を多用すると検査が骨抜きになる点だけ注意。

つまずきポイント

型チェックが通る=バグが無い、ではない

静的型は**「型レベルで表現できた間違い」だけ**を防ぎます。0除算、配列の範囲外、ロジックの誤り、null の取り扱いなどは、型を通ってもなお起こり得ます。型は強力な“第一の防壁”ですが、テストの代わりにはなりません。

動的型でも“型は在る”

動的型付け言語に「型が無い」わけではありません。値そのものは実行時にちゃんと型を持っています(Python の int、JS の number)。違うのは検査のタイミングが実行時にずれ込むこと。「型が無い」のではなく「検査が遅い」と捉えると正確です。

どう選ぶ?

  • 静的が向く: 大規模・多人数・長期保守、安全性が要件(決済・基盤)、IDE 補完を最大化したい
  • 動的が向く: プロトタイプ・スクリプト・データ分析、要件が流動的、とにかく速く回したい
  • 迷ったら漸進的型付けから。最初はゆるく、重要部分から型で締めていく。

型システムは“優劣”ではなくトレードオフの設定です。早く検査して安全を取るか、後回しにして身軽さを取るか——プロジェクトの寿命と規模で答えは変わります。関連して、値そのものの分類は変数とデータ型、例外の扱いはエラーハンドリングも合わせてどうぞ。

プログラミング Article

型システム(静的型付け vs 動的型付け)を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

型システム

比較で見る軸

難易度: intermediate / カテゴリ: プログラミング / タグ数: 3

導入後に効く点

静的=早期にバグ発見・補完が効く、動的=書き出しが速く柔軟。トレードオフであり優劣ではない。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
intermediate
カテゴリ
プログラミング
タグ数
3

判断チェックリスト

  • 自社の用途が「型システム / 言語」に近いか確認する。
  • 強みである「型システムは「この値で何ができるか」を決めるルール。検査のタイミングで静的(コンパイル時)と動的(実行時)に分かれる。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

型システム言語パラダイム型システム言語パラダイム
参考: 公式情報