declare(strict_types=1) で型の異なる引数を渡すと TypeError になる
ファイルの先頭でdeclare(strict_types=1)を宣言すると、関数の型宣言と異なる型の値を渡した際に自動変換されず、TypeErrorになります。strict_typesが無い場合は自動的に型変換されて実行が続きます。
エラーメッセージの読み方
Fatal error: Uncaught TypeError: add(): Argument #2 ($b) must be of type int, string given, called in main.php on line 6 and defined in main.php:3
main.php- ファイル名
3- 行番号 — 実際にクラッシュした行
TypeError- 例外クラス — 何が起きたか。ここを検索するのが最短です
add(): Argument #2 ($b) must be of type int, string given, called in main.php on line 6 and defined- 内容 — どの値が問題だったか
このエラーが出る典型パターン
パターン1
1 <?php 2 declare(strict_types=1); 3 function add(int $a, int $b): int { 4 return $a + $b; 5 } 6 echo add(1, "2" ); ^
strict_types=1を宣言したファイルでは、int型の引数に文字列を渡しても自動変換されずTypeErrorになります。数値そのものを渡す必要があります。
直し方: "2" を 2 にします。
パターン2
1 <?php 2 declare(strict_types=1); 3 function double(float $n): float { 4 return $n * 2; 5 } 6 echo double("3.5" ); ^
strict_typesが有効な状態でfloat型の引数に文字列を渡すとTypeErrorです。数値リテラルとして渡す必要があります。
直し方: "3.5" を 3.5 にします。
パターン3
1 <?php 2 declare(strict_types=1); 3 function repeat(string $s, int $times): string { 4 return str_repeat($s, $times); 5 } 6 echo repeat("ab", "3" ); ^
int型の引数に文字列"3"を渡すと、strict_types下では自動変換されずTypeErrorになります。
直し方: "3" を 3 にします。
パターン4
1 <?php 2 declare(strict_types=1); 3 function multiply(int $a, int $b): int { 4 return $a * $b; 5 } 6 echo multiply(4, "5" ); ^
strict_types=1の下では、int型の引数に文字列を渡しても自動変換されずTypeErrorになります。
直し方: "5" を 5 にします。
パターン5
1 <?php 2 declare(strict_types=1); 3 function greetName(string $n): string { 4 return "Hi " . $n; 5 } 6 echo greetName(5 ); ^
strict_types下ではstring型の引数に数値を渡してもTypeErrorになります。
直し方: 5 を "Al" にします。
よくある誤解
「PHPは型に緩い言語だから、int型の引数に文字列を渡しても自動変換されるはず」という思い込みは、strict_typesを宣言したファイルには当てはまりません。宣言した瞬間からそのファイル内の型チェックは厳格になります。
実務での勘所
strict_typesの効果は、宣言したファイルの中から関数を呼び出すときの引数の渡し方に対して働きます。呼ばれる側の関数がどのファイルで定義されているか(strict_typesを宣言しているかどうか)は関係ありません。つまり、strict_typesを宣言した自分のファイルから、宣言していない外部ライブラリの関数を呼び出しても、型の変換をしないという厳格な挙動は維持されます。「効果は呼び出し元のファイル単位で決まる」という理解が、strict_typesの正確な仕組みです。