DEV Community

Cover image for The "never" Type in PHP
Ash Allen
Ash Allen

Posted on • Originally published at ashallendesign.co.uk

4

The "never" Type in PHP

Introduction

There may be times when you're writing a function in PHP that you know will never return a value. This could be because the function always throws an exception, or maybe calls exit or die. In these cases, you might want to use the never type.

Admittedly, the never type isn't something I reach for very often, but it's useful in certain scenarios, especially when you want to make it clear to other developers that a function will not return normally.

In this article, we're going to explore the never type in PHP, how to use it, and some practical examples. I'll also include a cheat sheet at the end of this article that you can refer back to.

How to Use "never" in PHP

The never type was introduced in PHP 8.1 (released: November 2021) and is used to indicate that a function will never return. This signals to PHP, and other developers reading the code, that the function is not expected to return a value under any circumstances. This could be due to the function throwing an exception, or maybe calling something like exit or die.

The never type can only be used as a return type, and cannot be used as a parameter type.

Let's take a look at a quick example of how to use the never type in PHP:

public function doSomething(): never
{
    throw new Exception('Exception message here.');
}
Enter fullscreen mode Exit fullscreen mode

As we can see in the example above, the doSomething function uses the never return type because it will always throw an exception.

Let's change our example and update the doSomething function to return a value instead of throwing an exception. We're doing this to purposely break the code and show how PHP handles it:

public function doSomething(): never
{
    return 'This will cause an error';
}
Enter fullscreen mode Exit fullscreen mode

In our code example above, we are trying to return a string while using the never return type. This will result in a fatal error being thrown by PHP with the following message:

Fatal error: A never-returning function must not return in /in/32Ts2 on line 3
Enter fullscreen mode Exit fullscreen mode

Implicit Returns with "never"

If a function is declared with a never return type, isn't able to implicitly return a value. Doing so will also result in a fatal error.

For example, let's imagine we have a method that is used to publish a blog post:

namespace App\Services;

use App\Enums\ArticleStatus;
use App\Models\Article;

class ArticleService
{
    public function publishArticle(Article $article): never
    {
        $article->published_at = now();
        $article->status = ArticleStatus::Published;

        $article->save();
    }
}
Enter fullscreen mode Exit fullscreen mode

As we can see in the example above, the publishArticle method doesn't exit from the function or throw an exception. It also doesn't explicitly return a value. As a result, this means it will implicitly return and PHP will throw a fatal error when we try to call this method:

Fatal error: Uncaught TypeError: ArticleService::publishArticle(): never-returning function must not implicitly return
Enter fullscreen mode Exit fullscreen mode

Using "never" with Intersection Types

The never type cannot be used in PHP as part of an intersection type.

For example, let's take the following code snippet:

public function doSomething(): never&string
{
    throw new Exception('This will cause an error');
}
Enter fullscreen mode Exit fullscreen mode

Running this would result in a fatal error with the following message:

Fatal error: Type never cannot be part of an intersection type
Enter fullscreen mode Exit fullscreen mode

Using "never" with Union Types

The never type cannot be used in PHP as part of a union type.

For example, let's take the following code snippet:

public function doSomething(): never|string
{
    throw new Exception('This will cause an error');
}
Enter fullscreen mode Exit fullscreen mode

Running this would result in a fatal error with the following message:

Fatal error: never can only be used as a standalone type
Enter fullscreen mode Exit fullscreen mode

Example Use Case

Now that we've covered the basics of the never type, let's take a look at a practical example of how it can be used in a real-world scenario.

If you've used Laravel or Symfony before, you'll likely be familiar with the dd (dump and die) function. This function is used to dump variables and stop the script execution. It can be quite a handy tool for debugging to quickly inspect variables and see their contents.

This functionality is made available via the symfony/var-dumper package. Let's take a look at how the never type is used in the dd function (https://github.com/symfony/var-dumper/blob/7.3/Resources/functions/dump.php):

if (!function_exists('dd')) {
    function dd(mixed ...$vars): never
    {
        if (!in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true) && !headers_sent()) {
            header('HTTP/1.1 500 Internal Server Error');
        }

        if (!$vars) {
            VarDumper::dump(new ScalarStub('🐛'));

            exit(1);
        }

        if (array_key_exists(0, $vars) && 1 === count($vars)) {
            VarDumper::dump($vars[0]);
        } else {
            foreach ($vars as $k => $v) {
                VarDumper::dump($v, is_int($k) ? 1 + $k : $k);
            }
        }

        exit(1);
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, we don't need to fully understand the entire implementation of the dd function, but we can see that there are only two places where the function will finish running. Both of these places use exit(1), which means the script will terminate at that point. This is a perfect example of a function that will never return a value, and thus it is declared with the never return type.

Cheat Sheet

The never type in PHP:

  • Is used to indicate that a function will never return.
  • Can only be used as a return type.
  • Cannot be used as a parameter type.
  • Cannot be used in intersection types.
  • Cannot be used in union types.
  • Is available since PHP 8.1.

Conclusion

In this article, we've explored the never type in PHP, how to use it, and a practical example of how it's used in the symfony/var-dumper package's dd function. Hopefully, you should now feel confident using the never type in your own PHP code.

If you enjoyed reading this post, you might be interested in checking out my 220+ page ebook "Battle Ready Laravel" which covers similar topics in more depth.

Or, you might want to check out my other 440+ page ebook "Consuming APIs in Laravel" which teaches you how to use Laravel to consume APIs from other services.

If you're interested in getting updated each time I publish a new post, feel free to sign up for my newsletter.

Keep on building awesome stuff! 🚀

Embedded BI Dashboards are 💩 Building them yourself is 💩

Embedded BI Dashboards are 💩 Building them yourself is 💩

Use our developer toolkit to build fast-loading, native-feeling dashboards for your customers (without the sh*t).

Get early access

Top comments (2)

Collapse
 
fstrube profile image
Franklin Strube

I literally NEVER heard of this!

Collapse
 
ashallendesign profile image
Ash Allen

Haha! Yeah it's not something that I tend to see used a lot 😄

Sentry image

👀 Watch Us Break (and Fix) a Laravel App with Sentry

In this on-demand workshop, we push a Laravel + React app to the edge—then show exactly how to debug it using Sentry. From error tracking to Session Replays and full-stack performance monitoring, it's all here. Bonus: watch AI bots pitch in to clean up the mess.

🎥 Watch now + follow along

👋 Kindness is contagious

Explore this insightful piece, celebrated by the caring DEV Community. Programmers from all walks of life are invited to contribute and expand our shared wisdom.

A simple "thank you" can make someone’s day—leave your kudos in the comments below!

On DEV, spreading knowledge paves the way and fortifies our camaraderie. Found this helpful? A brief note of appreciation to the author truly matters.

Let’s Go!