Bird
Raised Fist0
PHPprogramming~15 mins

Union types in PHP - Deep Dive

Choose your learning style10 modes available
Overview - Union types
What is it?
Union types in PHP allow a variable or function parameter to accept more than one type of value. Instead of restricting a value to a single type, union types let you specify multiple possible types separated by a vertical bar (|). This helps make code more flexible while still keeping type safety. For example, a function can accept either an integer or a string as input.
Why it matters
Without union types, developers had to rely on loose typing or manual checks, which could cause bugs or unclear code. Union types solve this by letting the code explicitly say: 'this value can be one of these types.' This improves code clarity, reduces errors, and helps tools catch mistakes early. It makes PHP code safer and easier to understand, especially in larger projects.
Where it fits
Before learning union types, you should understand basic PHP types and type declarations for functions and variables. After mastering union types, you can explore advanced typing features like intersection types, nullable types, and generics in PHP. Union types build on the foundation of PHP's type system and prepare you for writing more robust and flexible code.
Mental Model
Core Idea
Union types let a value be one of several specified types, combining flexibility with type safety.
Think of it like...
Imagine a Swiss Army knife that can be a knife, a screwdriver, or scissors depending on what you need. Union types are like that knife: one tool with multiple possible functions.
┌───────────────┐
│   Variable    │
│  accepts any  │
│  of these:   │
│  int | string │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│  int value    │
│  or string    │
│  value       │
└───────────────┘
Build-Up - 7 Steps
1
FoundationBasic type declarations in PHP
🤔
Concept: Learn how PHP enforces types on function parameters and return values.
In PHP, you can declare the type of a function parameter or return value to ensure it matches. For example: function add(int $a, int $b): int { return $a + $b; } This function only accepts integers and returns an integer.
Result
If you call add(2, 3), it returns 5. If you call add('2', 3), PHP tries to convert '2' to int automatically.
Understanding basic type declarations is essential because union types extend this idea by allowing multiple types instead of just one.
2
FoundationWhat are union types in PHP?
🤔
Concept: Union types allow specifying multiple types for a parameter or return value using the | symbol.
Starting with PHP 8.0, you can write: function example(int|string $value): int|string { if (is_int($value)) { return $value * 2; } return strtoupper($value); } This means $value can be an int or a string, and the function returns the same.
Result
Calling example(5) returns 10; example('hi') returns 'HI'.
Union types let you write clearer, safer code that handles multiple types explicitly without losing type checking.
3
IntermediateNullable types vs union types
🤔Before reading on: Do you think nullable types are a special case of union types or something different? Commit to your answer.
Concept: Nullable types are a shorthand for a union type with null included.
In PHP, ?int means int|null. For example: function test(?int $value) { // $value can be int or null } This is equivalent to: function test(int|null $value) { // same meaning } Nullable types are just a simpler way to write a union with null.
Result
You can pass an integer or null to test().
Knowing nullable types are a subset of union types helps you understand PHP's type system consistency and syntax shortcuts.
4
IntermediateUsing union types with class and scalar types
🤔Before reading on: Can union types mix classes and scalar types like int or string? Commit to your answer.
Concept: Union types can combine scalar types and class/interface types in one declaration.
Example: class User {} function process(User|string $input) { if ($input instanceof User) { // handle User object } else { // handle string } } This function accepts either a User object or a string.
Result
You can call process(new User()) or process('guest').
Union types increase flexibility by allowing different kinds of values, including objects and simple types, in one place.
5
IntermediateType checking and union types at runtime
🤔Before reading on: Does PHP automatically convert types inside union types or throw errors? Commit to your answer.
Concept: PHP enforces union types strictly and does not convert types automatically inside unions.
If a function expects int|string, passing a float will cause a TypeError. For example: function test(int|string $value) {} test(3.14); // TypeError You must pass exactly one of the allowed types.
Result
Passing wrong types causes errors, helping catch bugs early.
Understanding strict enforcement prevents confusion and runtime bugs when using union types.
6
AdvancedUnion types with mixed and never types
🤔Before reading on: Can union types include 'mixed' or 'never' types? Commit to your answer.
Concept: The 'mixed' type means any type, so combining it with union types is redundant; 'never' means no value and cannot be combined in unions.
In PHP: - 'mixed' means any type, so writing int|mixed is just mixed. - 'never' means a function never returns; it can't be part of a union. Therefore, union types should avoid mixing these special types to keep meaning clear.
Result
Using mixed or never in unions is either redundant or invalid.
Knowing these special types' roles helps avoid confusing or meaningless union type declarations.
7
ExpertUnion types and backward compatibility challenges
🤔Before reading on: Do you think adding union types can break older PHP code silently or always causes errors? Commit to your answer.
Concept: Introducing union types can cause compatibility issues with older code expecting looser typing or different behaviors.
PHP 8.0 added union types, but older code might rely on implicit type juggling. For example, a function previously accepting any type now restricts inputs, causing TypeErrors. Also, reflection and type hints behave differently, requiring careful migration. Developers must test and update codebases to handle strict union types safely.
Result
Union types improve safety but require careful adoption to avoid breaking existing code.
Understanding backward compatibility challenges helps plan safe upgrades and avoid subtle bugs in large projects.
Under the Hood
At runtime, PHP checks the actual type of a value against the declared union types using internal type checking logic. When a function is called, PHP verifies if the argument matches any of the allowed types in the union. If not, it throws a TypeError. This check happens before the function body executes, ensuring type safety. The union type information is stored in the function's metadata and used by the engine during calls and reflection.
Why designed this way?
Union types were introduced to balance PHP's dynamic nature with modern type safety needs. Before union types, PHP was either loosely typed or forced to use workarounds like doc comments or manual checks. The design uses a simple syntax (|) to keep declarations readable and leverages existing type checking mechanisms. Alternatives like complex type systems or generics were avoided initially to keep PHP accessible and backward compatible.
┌───────────────┐
│ Function call │
└──────┬────────┘
       │
       ▼
┌─────────────────────────┐
│ Check argument type      │
│ against union types      │
│ (e.g., int|string)       │
└──────┬────────┬──────────┘
       │        │
   Matches?    No
       │        │
       ▼        ▼
┌───────────┐  ┌─────────────┐
│ Execute   │  │ Throw       │
│ function  │  │ TypeError   │
└───────────┘  └─────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does union type int|string accept float values? Commit to yes or no.
Common Belief:Union types accept any value that can be converted to one of the types, like float to int.
Tap to reveal reality
Reality:Union types require the value to be exactly one of the declared types; implicit conversions do not happen.
Why it matters:Assuming implicit conversion leads to unexpected TypeErrors and bugs when passing floats where int|string is expected.
Quick: Can you use union types with void return type? Commit to yes or no.
Common Belief:You can combine void with other return types in a union.
Tap to reveal reality
Reality:Void means no return value and cannot be combined in union types; it's exclusive.
Why it matters:Misusing void in unions causes syntax errors and confusion about function behavior.
Quick: Do union types allow mixing nullable and non-nullable types without explicit null? Commit to yes or no.
Common Belief:If you write int|string, null is allowed automatically.
Tap to reveal reality
Reality:Null is not included unless explicitly stated, e.g., int|string|null or ?int.
Why it matters:Assuming null is allowed causes unexpected null-related bugs and runtime errors.
Quick: Can union types be used in property declarations in PHP 8.0? Commit to yes or no.
Common Belief:Union types can be used anywhere types are declared, including properties.
Tap to reveal reality
Reality:PHP 8.0 supports union types for parameters and returns but not for typed properties until PHP 8.1.
Why it matters:Trying to use union types in properties in PHP 8.0 causes syntax errors and confusion.
Expert Zone
1
Union types do not support recursive or nested unions; each union is flat and explicit.
2
When multiple union types are combined in inheritance, PHP requires compatible declarations, which can be tricky to manage.
3
Reflection API treats union types as a collection of single types, requiring careful handling when inspecting code dynamically.
When NOT to use
Avoid union types when you need more complex type relationships like intersections or generics, which PHP does not support natively. Also, if your codebase targets PHP versions before 8.0, union types are not available. In those cases, use doc comments or manual type checks instead.
Production Patterns
In real-world PHP applications, union types are used to handle flexible input data, such as accepting IDs as int|string or processing different object types in one function. They improve API clarity and reduce boilerplate type checks. Frameworks and libraries adopt union types to enforce contracts while supporting multiple data formats.
Connections
TypeScript union types
Same pattern in a different language
Understanding PHP union types helps grasp TypeScript's similar feature, showing how multiple languages solve flexible typing with unions.
Set theory in mathematics
Union types correspond to the union of sets of possible values
Seeing union types as set unions clarifies why a value must belong to any one of the specified types, linking programming to fundamental math concepts.
Natural language ambiguity
Union types reflect how words can have multiple meanings depending on context
Recognizing that union types model multiple possible meanings helps understand ambiguity management in language and programming.
Common Pitfalls
#1Passing a float to a union type expecting int|string
Wrong approach:function test(int|string $value) {} test(3.14);
Correct approach:function test(int|string $value) {} test(3); // or test('3.14');
Root cause:Misunderstanding that union types do not allow implicit type conversions.
#2Assuming null is allowed without explicit declaration
Wrong approach:function example(int|string $value) {} example(null);
Correct approach:function example(int|string|null $value) {} example(null);
Root cause:Confusing nullable types with union types that exclude null by default.
#3Using union types in property declarations in PHP 8.0
Wrong approach:class A { public int|string $prop; }
Correct approach:class A { public int|string $prop; // valid only in PHP 8.1+ }
Root cause:Not knowing union types for properties were introduced after PHP 8.0.
Key Takeaways
Union types let you specify multiple allowed types for variables, parameters, and return values, increasing flexibility while keeping type safety.
They use the vertical bar (|) to separate types and require exact matches without implicit conversions.
Nullable types are a special case of union types that include null explicitly.
Union types improve code clarity and error detection but require careful use to avoid compatibility and runtime issues.
Understanding union types connects programming with broader concepts like set theory and language ambiguity, enriching your mental model.

Practice

(1/5)
1. What does a union type in PHP allow you to do?
function example(int|string $value) {}
easy
A. Only accept integer values
B. Accept multiple types for a parameter or return value
C. Only accept string values
D. Combine two functions into one

Solution

  1. Step 1: Understand union type syntax

    The | symbol between types means the parameter can be either type.
  2. Step 2: Analyze the example function

    The function accepts either an int or a string as input.
  3. Final Answer:

    Accept multiple types for a parameter or return value -> Option B
  4. Quick Check:

    Union types allow multiple types [OK]
Hint: Look for the | symbol to spot union types [OK]
Common Mistakes:
  • Thinking union types combine functions
  • Assuming only one type is allowed
  • Confusing union types with type casting
2. Which of the following is the correct syntax for a union type in PHP 8+?
function test(?? $param) {}
easy
A. int|string, float $param
B. int&string $param
C. int|string&float $param
D. int|string $param

Solution

  1. Step 1: Recall union type syntax

    Union types use the | symbol between types, e.g., int|string.
  2. Step 2: Check each option

    int|string $param uses | correctly. int&string $param uses & which is intersection, not union. int|string&float $param mixes union and intersection incorrectly. int|string, float $param uses a comma which is invalid.
  3. Final Answer:

    int|string $param -> Option D
  4. Quick Check:

    Union types use | symbol [OK]
Hint: Union types always use | between types [OK]
Common Mistakes:
  • Using & instead of | for union types
  • Separating types with commas
  • Mixing intersection and union syntax incorrectly
3. What will be the output of this PHP code?
function showType(int|string $value) {
    if (is_int($value)) {
        return "Integer: $value";
    } else {
        return "String: $value";
    }
}

echo showType(10) . "\n";
echo showType("hello") . "\n";
medium
A. 10\nhello
B. String: 10\nInteger: hello
C. Integer: 10\nString: hello
D. Error: Type mismatch

Solution

  1. Step 1: Understand the function behavior

    The function checks if the input is an integer or string and returns a formatted string accordingly.
  2. Step 2: Trace the calls

    Calling with 10 (int) returns "Integer: 10". Calling with "hello" (string) returns "String: hello".
  3. Final Answer:

    Integer: 10\nString: hello -> Option C
  4. Quick Check:

    Type check returns correct output [OK]
Hint: Check type with is_int or is_string inside function [OK]
Common Mistakes:
  • Assuming output is just values without labels
  • Confusing string and int outputs
  • Expecting a type error for valid union types
4. Identify the error in this PHP function using union types:
function add(int|float $a, int|float $b): int|float {
    return $a + $b;
}

add(5, "10");
medium
A. Passing a string "10" instead of int or float causes a type error
B. Return type should be only int
C. Union types cannot be used in return types
D. Function should not accept two parameters

Solution

  1. Step 1: Check parameter types

    The function expects parameters of type int or float only.
  2. Step 2: Analyze the function call

    The call passes 5 (int) and "10" (string). String is not allowed, causing a type error.
  3. Final Answer:

    Passing a string "10" instead of int or float causes a type error -> Option A
  4. Quick Check:

    Parameter types must match union types exactly [OK]
Hint: Check argument types match union types exactly [OK]
Common Mistakes:
  • Assuming string '10' is accepted as int
  • Thinking union types disallow return types
  • Ignoring parameter count
5. You want a function that accepts either an array of integers or a single integer and returns the sum. Which union type and code is correct?
function sumValues(?? $input): int {
    if (is_array($input)) {
        return array_sum($input);
    }
    return $input;
}
hard
A. int|array $input
B. int|string $input
C. array|float $input
D. int|bool $input

Solution

  1. Step 1: Identify input types needed

    The function accepts either a single integer or an array of integers.
  2. Step 2: Match union type to input

    int|array $input uses int|array, which matches the requirement. Others include wrong types like string, float, or bool.
  3. Final Answer:

    int|array $input -> Option A
  4. Quick Check:

    Union type matches all accepted input types [OK]
Hint: Match union types exactly to all input types needed [OK]
Common Mistakes:
  • Using string or bool instead of array
  • Not including all input types in union
  • Confusing float with int
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard