Lesson 71 of 100
Types15 min5 checksPHP 8.5

Use Strict Scalar Type Checking with declare(strict_types=1)

Learn how declare(strict_types=1) changes scalar type checks at call sites, when a TypeError is thrown, and how to test it with local helper functions.

01 · THE IDEAREAD → TRY → LEARN

Why strict types matter

A type declaration such as int $n says what a function expects. What happens when a caller passes something else depends on the typing mode. By default PHP uses coercive typing: it converts a value to the declared scalar type when it can. A string '5' passed to an int parameter quietly becomes the integer 5. That is convenient, but it can hide bugs, such as an unvalidated form value reaching code that assumed integers.

Strict mode removes the conversion. Put declare(strict_types=1); as the very first statement of a file, and scalar type declarations in that file accept only values of exactly the declared type. Anything else throws a TypeError.

The one exception is that an int is allowed where float is declared.

The call site decides

The setting belongs to the file that makes the call, not the file that defines the function. If a strict file calls a function, the arguments are checked strictly. If a file without the declaration calls the same function, the caller's coercive behavior applies and values are converted. For return values, the example below shows a strict file rejecting a mismatched return.

Two more limits to remember:

  • Strict typing only covers scalar type declarations (int, float, string, bool).
  • Calls made from inside internal PHP functions are not affected by strict_types.

Worked example: strict accepts exact types

In this file, addInts() receives integers and halve() receives an integer where a float is declared. Both calls are valid in strict mode.

Example
<?php
declare(strict_types=1);

function addInts(int $a, int $b): int
{
    return $a + $b;
}

function halve(float $n): float
{
    return $n / 2;
}

echo json_encode([addInts(2, 3), halve(5)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
[5,2.5]

The int to float widening is the only automatic conversion strict mode performs.

Strict mode throws instead of converting

Now pass a numeric string. With the declaration present, the call fails, and we can catch the error to show that it happened.

Example
<?php
declare(strict_types=1);

function addInts(int $a, int $b): int
{
    return $a + $b;
}

try {
    echo addInts('5', 3);
} catch (TypeError $e) {
    echo "TypeError caught\n";
}
Output
TypeError caught

In real programs you usually do not catch this error around every call. Instead, validate or cast input at the boundary of your program, then let strict typing protect the inner code.

The same call without the declaration

Here the file has no declare. The string '5' is converted to an integer, and the float 1.0, which has no fractional part, is converted to 1.

Example
<?php
function addInts(int $a, int $b): int
{
    return $a + $b;
}

echo json_encode([addInts('5', 3), addInts(1.0, 2)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
[8,3]

The function body is identical in the last two examples. Only the caller's mode changed the result.

Common mistakes

  1. Placing declare too late. It must be the first statement in the file, directly after <?php.
  2. Expecting it to protect other files. Each file opts in separately.
  3. Forgetting null. null is not accepted by a non-nullable int parameter. Use ?int when null is valid.
  4. Using (int) casts to silence errors. A cast turns 'abc' into 0 and hides the very problem strict mode is meant to reveal.

Exercise contract

Write doubleStrict(array $values): array. The starter file already enables strict types and provides a helper, doubleInt(int $n): int. For each element of $values, in order, call doubleInt() from your function. If the call succeeds, append the doubled integer to the result. If it throws a TypeError, append the string 'TypeError' instead. Return the result array.

Because the helper is called locally from a strict file, '5', true, null and 'abc' must all produce 'TypeError', while real integers, including 0 and negatives, are doubled. An empty array returns an empty array.

Recap

  • declare(strict_types=1); goes first in the file and affects calls made from that file.
  • Strict mode accepts exact scalar types, plus int for float.
  • A mismatch throws TypeError rather than converting.
  • Without the declaration, PHP coerces values where it can.
Before you start

Functions · Arrays · Types

You’ll practice
  • Explain declare(strict_types=1) at call sites using locally called helpers
  • Implement and test a deterministic PHP 8.4 function
Your task

Make doubleStrict() pass all 5 checks. Run your code as often as you like, then check your answer.

exercise.phpSaved in this browserPHP 8.5
CONSOLE & CHECKS● Ready

Ready when you are

Your output will appear here.
Make it work. Then make it pass.

PHP loads on your first run. Each check starts fresh. Your code stays in this browser; clearing site data removes your progress. A check or the task looks wrong? Report a problem with this exercise.