Conversation
|
Made some progress. Interestingly this works: /**
* @template M of self::TYPES
* @template T of key-of<M>
* @param T $type
*
* @return new<M[T]>
*/
public static function get(string $type) : object
{
$class = self::TYPES[$type];
return new $class('now');
}But this doesn't: /**
* @template T of key-of<self::TYPES>
* @param T $type
*
* @return new<self::TYPES[T]>
*/
public static function get2(string $type) : object
{
$class = self::TYPES[$type];
return new $class('now');
}
/**
* @template T of class-string
* @param T $type
*
* @return new<T>
*/
public static function create(string $type) : object
{
return new $type();
}I have the feeling this has something to do with \PHPStan\Type\NewObjectType::isResolvable: public function isResolvable(): bool
{
return !TypeUtils::containsTemplateType($this->type);
}Maybe we should allow |
|
This is already possible, without /**
* @template T of object
* @param class-string<T> $type
*
* @return T
*/
public static function create(string $type) : object
{
return new $type();
} |
I don't think it does. Other late-resolvable types look the same. You need to launch Xdebug and see what's going on :) |
|
Updated the PR. I think this is ready now.
/**
* @template M of self::TYPES
* @template T of key-of<M>
* @param T $type
*
* @return new<M[T]>
*/
public static function get(string $type) : object
{
$class = self::TYPES[$type];
return new $class('now');
}For simple cases, you can use: /**
* @template T of object
* @param class-string<T> $type
*
* @return T
*/
public static function create(string $type) : object
{
return new $type();
} |
|
What was the problem described here? #3050 (comment) |
|
I guess writing it like this just will not be possible: /**
* @template T of key-of<self::TYPES>
* @param T $type
*
* @return new<self::TYPES[T]>
*/
public static function get2(string $type) : object
{
$class = self::TYPES[$type];
return new $class('now');
}When I use your suggested syntax (with another template), it works. |
|
@ruudk Can you please send this working example with a description to this article? https://phpstan.org/blog/generics-by-examples Source is here: https://github.com/phpstan/phpstan/blob/1.11.x/website/src/_posts/generics-by-examples.md |
|
Writing |
|
@rvanvelzen Nice! I added this example also to the test. |
Done in phpstan/phpstan#10971 |
@rvanvelzen Interesting, Maybe that fix will make this possible without Edit: tried it, doesn't work. |
|
The improvement to phpdoc-parser has been merged here, please rebase this branch and try out what it improves (add tests for previously impossible use-cases). You can also try it out in the playground https://phpstan.org/try, it has been updated too. |
This makes it possible that a new instance of a class-string will be returned. ```php /** * @var array<string, class-string> */ private const TYPES = [ 'foo' => DateTime::class, 'bar' => DateTimeImmutable::class, ]; /** * @template T of key-of<self::TYPES> * @param T $type * * @return new<self::TYPES[T]> */ public static function get(string $type) : ?object { $class = self::TYPES[$type]; return new $class('now'); } ``` See phpstan/phpstan#9704 The work was done by @rvanvelzen in a gist. I just created the PR for it. Co-Authored-By: Richard van Velzen <rvanvelzen1@gmail.com>
|
@ondrejmirtes Rebased. With the fix in phpdoc-parser we can remove the parenthesis. This simplifies the syntax. Updated the example too. |
|
Awesome, thank you! |
|
Did we just remove the need for /**
* @template T of key-of<self::TYPES>
* @param T $type
*
* @return new<self::TYPES[T]>
*/ |
|
No, probably not, see phpstan/phpstan#9521 |
This makes it possible that a new instance of a class-string will be returned.
See phpstan/phpstan#9704
The work was done by @rvanvelzen in a gist. I just created the PR for it.