Type Declarations & Typed Properties

PHP is dynamically typed, but you don't have to fly blind. Type declarations let you state what each parameter, return value, and property should be — and PHP enforces it. Turn on strict_types and a whole class of bugs becomes an immediate, located error.

Learn Type Declarations & Typed Properties in our free PHP course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…

Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ Typing Parameters & Returns

Put a type before each parameter, and after the closing parenthesis put : type for the return. PHP enforces these on every call. The scalar types are int , float , string , bool ; plus array , object , class names, and the return-only void . By default PHP runs in coercive mode and will convert a compatible value (note the string "21" below becoming an int).

2️⃣ Strict Mode

Add declare(strict_types=1); as the very first statement of a file to turn off coercion: types must now match exactly, and a mismatch throws a TypeError . This is the recommended default for serious code — it catches wrong types right at the boundary instead of letting a silently-converted value cause a subtle bug deeper in.

3️⃣ Nullable & Union Types

Real values are sometimes "or nothing". A leading ? makes a type nullable : ?string means a string or null (shorthand for string|null ). For multiple real types, PHP 8.0's union syntax lists them with a pipe: int|string .

4️⃣ Typed Properties

Since PHP 7.4 you can type class properties directly. There's one gotcha worth burning into memory: a typed property with no default isn't null — it's uninitialised , and reading it before you assign throws an error. Give it a default, set it in the constructor, or make it nullable if "not set yet" is valid.

Now you try — fill in each ___ using the 👉 hint, then run it and check against the Output panel.

These lines make a strictly-typed file that prints 10 — but they're scrambled. Put them in the order PHP requires.

declare(strict_types=1) must be first ( C ) — it's a fatal error anywhere else. Then define the function: signature ( D ), body ( B ), close ( E ), and finally call it ( A ), which prints 10 .

1. Coercive mode (no strict_types). What prints?

10 — in coercive mode PHP converts the numeric string '9' to the int 9, then adds 1.

2. With declare(strict_types=1) at the top, what happens?

A TypeError is thrown — strict mode refuses to coerce the string '9' into an int.

It throws an Error : "Typed property U::$name must not be accessed before initialization." It has no value yet — not even null.

📋 Quick Reference — Types

No code is filled in this time — just a brief and an outline. Write it yourself, run it on onecompiler.com/php or your own machine, then check your result against the expected output in the comments.

Practice quiz

In coercive mode (no strict_types), what does double('21') print for function double(int $n): int { return $n * 2; }?

  • A TypeError
  • 2121
  • 42
  • 0

Answer: 42. Coercive mode converts the numeric string '21' to int 21, then doubles it to 42.

With declare(strict_types=1), what does calling double('21') do?

  • Throws a TypeError
  • Returns 42
  • Returns '2121'
  • Returns null

Answer: Throws a TypeError. Strict mode refuses to coerce a string into an int, so a TypeError is thrown.

Where must declare(strict_types=1); appear?

  • Anywhere in the file
  • At the end of the file
  • Inside every function
  • As the very first statement of the file

Answer: As the very first statement of the file. It must be the very first statement; placing it anywhere else is a fatal error.

What does ?string mean as a type?

  • An optional argument
  • A string or null
  • A string only
  • A union of string and int

Answer: A string or null. A leading ? makes a type nullable: ?string is shorthand for string|null.

Which type accepts both an int and a string argument?

  • int|string
  • int&string
  • ?int
  • int,string

Answer: int|string. Union types (PHP 8.0) list multiple types with a pipe: int|string.

What happens when you read a typed property that has no default before assigning it?

  • It returns null
  • It returns 0
  • An Error: it must not be accessed before initialization
  • It returns an empty string

Answer: An Error: it must not be accessed before initialization. A typed property with no default is uninitialised — not null — and reading it before assignment throws an Error.

Even in strict mode, which conversion does PHP still allow for typed arguments?

  • Passing a string where an int is expected
  • Passing an int where a float is expected (widening)
  • Passing an array where a string is expected
  • Passing a bool where a string is expected

Answer: Passing an int where a float is expected (widening). The one sanctioned exception is widening an int to a float, because it loses nothing.

What does the void return type mean?

  • The function returns null
  • The function returns an empty array
  • The function never finishes
  • The function returns nothing

Answer: The function returns nothing. : void declares that a function returns no value; using return $x; in it is an error.

Which is the correct way to give a nullable typed property a starting value?

  • public string $note = null;
  • public ?string $note = null;
  • public string $note;
  • public ?string $note;

Answer: public ?string $note = null;. A nullable property can default to null: public ?string $note = null; — a non-nullable string cannot.

What is the recommended default for serious typed PHP code?

  • Avoid type declarations entirely
  • Use only union types
  • Enable declare(strict_types=1) in every file
  • Rely on coercion everywhere

Answer: Enable declare(strict_types=1) in every file. Most teams enable strict types everywhere because catching a TypeError at the boundary beats chasing wrong values.