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) {
//
}
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.