Search code examples
phptypesphpstorm

PhpStorm inferring `mixed` type on my typed properties


I've been working recently with classes that initialize themselves from an array of data, and have typed properties which are set with values retrieved from the array.

The properties are typed, which means PHP will throw a TypeError if anything besides the specified type is passed in.

However, PhpStorm appears to be propogating the mixed type from the array access to the class property.

I'm struggling to explain it in words, so here's an example script:

<?php

class TestClass
{
    public readonly string $myString;
    public readonly int $myInt;
    public readonly array $myArray;

    public function __construct(array $src)
    {
        $this->myString = $src['stringVal'];
        $this->myInt = $src['intVal'];
        $this->myArray = $src['array'];
    }
}

$arr = [
    'stringVal' => 123,
    'intVal' => "I am a string",
    'array' => null,
];

$x = new TestClass($arr); // throws TypeError from within the constructor

$y = new TestClass($x->myInt); // PhpStorm doesn't see anything wrong with this???

You can see that there are types on all 3 of the properties. You can look at the script and see that it will fail. The script as written throws a TypeError exactly as you'd expect when it tries to set $this->myString.

However, if I hover over any of the class properties, PhpStorm is adding the mixed type to the property:

Screenshot showing the PhpStorm propup with mixed|string as the type on the property $myString

Since PhpStorm is treating all of the properties as "x or mixed", it doesn't see anything wrong with the obviously incorrect last line of the script, where we're trying to pass an int to the constructor, which requires an array:

Screenshot showing that PhpStorm doesn't show any error on the final line of the script

How can I get PhpStorm to stop inferring mixed on these properties?

Update: it's not only mixed coming from an array, it seems that PhpStorm is just assuming that whatever happens in the constructor is valid, regardless of the types on the properties(?)

Another example:

class TestClass2
{
    public readonly int $myInt;

    public function __construct()
    {
        $this->myInt = "hello world";
    }
}

The constructor throws a TypeError, again just as you'd expect. But PhpStorm seems content to assume that the property will accept a string:

Screenshot showing PhpStorm's popup with the type int|string on $myInt


Solution

  • I filed a bug report to JetBrains, and they gave me the following workaround:

    As a workaround, you can either mark the file with declare(strict_types=1); or enable the PHP | Type compatibility | Strict type checking rules violation: Enable for all files.

    In my case, the code inspection setting was most appropriate and solved the issue for me.