Search code examples
phpvisual-studio-codeintellisensephpstan

Is their a way of passing along typehint to callable in phpstan/intellisense? PHP


I have a factory method whose signature is similar to this:

/**
 * @param class-string $class
 * @param callable? $callback
 * @return static
 */
public function instance(string $class, callable? $callback);

From the first parameter, an instance is created. Rather than the instance being returned, $this is returned instead - so an optional callback can be provided and the factory invokes it, passing the new instance.

What I want to know is - given the string passed is literal, can phpstan/vscode be told that the argument passed to the callable is an instance of my specified class, so that when I refer to the object inside the callable it can make suggestions of available methods/props, and so that phpstan can not grumble about missing methods, without me also typehinting the argument of the callable?

The object created does extend a common base class, but child classes will have their own methods.

Maybe clearer with an example of a call:

$obj->factory(Foo::class, function ($foo) {
   //
}

And I’m hoping to avoid repeating the explicit hint:

$obj->factory(Foo::class, function (Foo $foo) {
   //
}

Solution

  • You can use generics to achieve this.

    Check out this example: https://phpstan.org/r/cf596842-d9cb-4996-b2af-08d6683dd366

    Basically you'd need a declaration like this one:

    /**
     * @template T of object
     * @param class-string<T> $class
     * @param (callable(T):mixed)|null $callback
     * @return static
     */
     public function instance(string $class, callable|null $callback)
    

    Here we are saying that the callable has one required argument. And it's type is the object of the first parameter that is passed into the instance method.

    You can read more about generics here and here.