型システム

プログラムの正しさを保証する仕組み

静的型付け vs 動的型付け

静的型付け

コンパイル時に型チェック。実行前にエラーを発見。

Go, Rust, TypeScript, Java

動的型付け

実行時に型チェック。柔軟だがランタイムエラーのリスク。

Python, Ruby, JavaScript

強い型付け vs 弱い型付け

強い型付け

暗黙の型変換を制限。明示的な変換が必要。

Python, Go, Rust

弱い型付け

暗黙の型変換が発生。予期しない結果の可能性。

JavaScript, C

1// JavaScriptの弱い型付け例
2"5" + 3 // "53" (文字列連結)
3"5" - 3 // 2 (数値演算)
4[] + {} // "[object Object]"
5{} + [] // 0

型推論

コンパイラが文脈から型を自動的に推論。明示的な型注釈を減らしつつ型安全性を維持。

1// Go - 型推論
2x := 42 // int と推論
3y := "hello" // string と推論
4z := []int{1,2,3} // []int と推論
5
6// 明示的な型宣言
7var a int = 42
8var b string = "hello"
1// TypeScript - 型推論
2const x = 42; // number
3const y = "hello"; // string
4const arr = [1, 2, 3]; // number[]
5
6// 明示的な型注釈
7const z: number = 42;
8const list: string[] = ["a", "b"];

ジェネリクス

型をパラメータ化し、再利用可能なコードを型安全に記述。

1// Go 1.18+ ジェネリクス
2func Map[T, U any](slice []T, f func(T) U) []U {
3 result := make([]U, len(slice))
4 for i, v := range slice {
5 result[i] = f(v)
6 }
7 return result
8}
9
10// 使用例
11nums := []int{1, 2, 3}
12doubled := Map(nums, func(n int) int { return n * 2 })
1// TypeScript ジェネリクス
2function map<T, U>(arr: T[], fn: (item: T) => U): U[] {
3 return arr.map(fn);
4}
5
6// 使用例
7const nums = [1, 2, 3];
8const doubled = map(nums, n => n * 2);
9const strings = map(nums, n => n.toString());

Null安全性

言語アプローチ
Goゼロ値 + errorval, err := fn()
RustOption<T>Some(val) / None
TypeScriptstrictNullChecksT | null | undefined
KotlinNullable型String? vs String
1// Rust - Option型
2fn find_user(id: u32) -> Option<User> {
3 // ユーザーが見つかればSome、なければNone
4 if let Some(user) = users.get(&id) {
5 Some(user.clone())
6 } else {
7 None
8 }
9}
10
11// 使用時は必ずハンドリングが必要
12match find_user(123) {
13 Some(user) => println!("Found: {}", user.name),
14 None => println!("User not found"),
15}

構造的型付け vs 名目的型付け

構造的(Structural)

同じ構造を持てば互換性あり(ダックタイピング)

TypeScript, Go

名目的(Nominal)

明示的に宣言された関係のみ互換性あり

Java, C#, Rust

1// TypeScript - 構造的型付け
2interface Point {
3 x: number;
4 y: number;
5}
6
7// 同じ構造を持つオブジェクトは互換
8const p: Point = { x: 1, y: 2 };
9
10// 追加プロパティがあっても構造が満たされればOK
11const p3d = { x: 1, y: 2, z: 3 };
12function printPoint(point: Point) {
13 console.log(point.x, point.y);
14}
15printPoint(p3d); // OK

型システムの利点

早期エラー検出

コンパイル時に多くのバグを発見

ドキュメント

型自体がコードの仕様を表す

IDE支援

補完、リファクタリング、ナビゲーション

安全なリファクタリング

型エラーで影響範囲を特定