What Is the "never" Return Type in PHP?

Introduced in PHP 8.1, never is a return type that can be added to functions or methods to indicate that:

  1. It will never return a value (including an empty return), and;
  2. It's guaranteed to halt further execution of the script, either by throwing an exception or by terminating with a die or exit call.

For example:

// PHP 8.1+
function redirect(string $url): never {
    header("Location: $url");
    exit();
}

redirect('https://www.designcise.com');
// anything that follows is guaranteed to not be executed

If a function/method with never return type does not throw an exception or terminate with a die or exit call, then PHP will throw a TypeError:

// PHP 8.1+
function redirect(string $url): never {
    header("Location: $url");
}

// TypeError: redirect(): never-returning function must not implicitly return
redirect('https://www.designcise.com');

never is a "bottom" type, which means that it is a subtype of every other type (including void), and there's nothing more specific than it. It obeys the following rules:

  • Return type covariance is allowed;
  • Return type contravariance is not allowed;
  • It cannot be used in a union or intersection type.

In the following example, you can see how return type covariance is allowed:

// PHP 8.1+
class A {
    public function foo(): string {}
}

class B extends A {
    public function foo(): never {}
}

In the following example, you can see how return type contravariance is not allowed:

// PHP 8.1+
class A {
    public function foo(): never {}
}

class B extends A {
    // Fatal error: Declaration of B::foo(): string must be compatible with A::foo(): never
    public function foo(): string {}
}

In the following examples, you can see how never cannot be used in a union or intersection type:

// PHP 8.1+
class A {
    // Fatal error: never can only be used as a standalone type
    public function foo(): never | string {}
}
// PHP 8.1+
class A {
    // Fatal error: Type never cannot be part of an intersection type
    public function foo(): never & string {}
}

This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.