-
Notifications
You must be signed in to change notification settings - Fork 507
Introduce new
type
#3050
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce new
type
#3050
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
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.