-
-
Notifications
You must be signed in to change notification settings - Fork 147
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
[3.x] Add template annotations #188
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.
@simPod Thanks for bringing this up!
I think this feature makes perfect sense, but I'd like to make sure this is complete before merging this.
In particular, can you add some automated tests to verify this works as expected?
On top of this, phpstan also supports generics, does it make sense to address this as part of the PR?
@clue thanks for input. I'll look into how to test this. Also note this is only partial implementation (for happy path) as both psalm and phpstan do not support default template types yet (it's impossible to resolve template to a type when This is resolving Crosslinks:
phpstan reads |
src/PromiseInterface.php
Outdated
@@ -44,7 +48,7 @@ public function then(?callable $onFulfilled = null, ?callable $onRejected = null | |||
* Since the purpose of `done()` is consumption rather than transformation, | |||
* `done()` always returns `null`. | |||
* | |||
* @param callable|null $onFulfilled | |||
* @param callable(mixed):TResolve|null $onFulfilled |
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.
I'd think this should be TResolved
, but it's not defined on this method so I don't think that would work? Not sure what this is supposed to do here.
I'll wait for default promise value support in SA since it's fairly useless without it |
@simPod thanks for your work on this so far 👍 To keep you updated: |
Thank you for update and pushing it forward! |
One major thing for me was to tackle the bigger picture, so not just this promise package. But also |
@simPod Just a heads up: I'm going to make a bunch of suggested changes based on https://psalm.dev/r/22a9692a97 later today. But want thank you for your work so far on this and for pushing it forward so far 👍 |
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.
When making the suggestions, I realized I forgot about the other methods, will update vimeo/psalm#7559 and this PR's suggestions soon
FYI just put up #223 as a draft for the 2.x branch so I can pull it in through composer and test it out again in a project without having to manually edit files again. Will try to get back shortly and hope live doesn't get in between again |
* @psalm-template T | ||
* @psalm-template R |
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.
Any reason this can not just use @template
?
@simPod Hey if you don't mind I'm going to use your commit as a base to get template annotations + some additional type insurance in. |
Awesome 👌🏿
…On Fri, Jun 23, 2023, 01:00 Cees-Jan Kiewiet ***@***.***> wrote:
@simPod <https://github.com/simPod> Hey if you don't mind I'm going to
use your commit as a base to get template annotations + some additional
type insurance in.
—
Reply to this email directly, view it on GitHub
<#188 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACQAJLSS6A4Q46K5ZQJXKLXMS57TANCNFSM4ZGKGHSA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
PR is up at: #247 |
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
Adds template annotations turning the `PromiseInterface` into a generic. Variables `$p1` and `$p2` in the following code example both are `PromiseInterface<int|string>`. ```php $f = function (): int|string { return time() % 2 ? 'string' : time(); }; /** * @return PromiseInterface<int|string> */ $fp = function (): PromiseInterface { return resolve(time() % 2 ? 'string' : time()); }; $p1 = resolve($f()); $p2 = $fp(); ``` When calling `then` on `$p1` or `$p2`, PHPStan understand that function `$f1` is type hinting its parameter fine, but `$f2` will throw during runtime: ```php $p2->then(static function (int|string $a) {}); $p2->then(static function (bool $a) {}); ``` Builds on top of reactphp#246 and reactphp#188 and is a requirement for reactphp/async#40
I was considering adapting this lib for promises though it's currently impossible to be type-safe with it.
I found this psalm plugin https://github.com/Bocmah/psalm-reactphp-promise-plugin that only includes stubs for psalm. So I was thinking it can be simply ported into this promise lib so it's also supported by phpstan and by any static analysis overall without need for any additional setup.