Uh oh!
There was an error while loading. Please reload this page.
[Types] Add JsonDecodeDynamicReturnTypeExtension - #89
Conversation
33460c9 to
a4ca889CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| # in PHP 7.1, the json_decode() 2nd parameter requires bool, while PHP 7.2 it's null|int | ||
| - name: "Downgrade nette/utils" | ||
| if: matrix.php-version == '7.1' | ||
| run: "composer require --dev nette/utils:^2.3 nette/forms:^2.4 --update-with-dependencies" |
There was a problem hiding this comment.
2nd arg of json_decode() takes different types in PHP 7.1 and PHP 7.2+
7743920 to
f796944Compare
ondrejmirtes
left a comment
There was a problem hiding this comment.
What I'd like to see instead is to have this kind of logic for json_decode in phpstan-src. When that's done, this Nette extension can simply delegate the logic with $scope->getType(new FuncCall('json_decode', $args)). Of course $args would be composed based on the FORCE_ARRAY argument so that json_decode is called with $associative=true.
TomasVotruba
commented
Jan 30, 2022
I actually tried to add function extension first but PHPStan analysed only non-basic function. Not sure why. Apart that, is the type resolution in tests here correct? |
ondrejmirtes
commented
Jan 30, 2022
Instead of the whole |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| // scalar types with stdClass | ||
| return new UnionType([ | ||
| new ObjectType(stdClass::class), |
There was a problem hiding this comment.
It can still be an array here.
There was a problem hiding this comment.
I guess the stdclass could contain a array of other things?
There was a problem hiding this comment.
You don't have to guess: https://3v4l.org/qsjVh
BTW I worry that these precise types would become really annoying. Right now people working with json_decode() get some errors on level 9, but with these union types it would be much sonner - on level 7. I think the best course of action is to return "MixedType without stdClass" with FORCE_ARRAY, and normal "MixedType" without FORCE_ARRAY.
MixedType is subtractable - new MixedType(true, new ObjectType(\stdClass::class)) means mixed without stdClass.
There was a problem hiding this comment.
MixedType is subtractable
Cool, that's a new trick to me.
I think the best course of action is to return "MixedType without stdClass" with FORCE_ARRAY, and normal "MixedType" without FORCE_ARRAY.
Do you mean like this?
if ($isForceArray) {
returnnewMixedType(true, newObjectType(\stdClass::class));
}
returnnewMixedType(true);It might be change with more strict approach, but it would be more correct. The reason we made this extension for our project is to make sure there is only scalar value or stdClass. Mixed includes anything, objects, array of object etc.
Yet the DX is important, I understand. It might be useful to enable this only since level 9+.
ondrejmirtes
commented
Jan 30, 2022
Just to reiterate - I still want this to be submitted as a |
TomasVotruba
commented
Jan 30, 2022
@ondrejmirtes I understand that, I just want to make it work and confirm here, so we don't jump back and forth. |
f796944 to
1041390Compare@ondrejmirtes As for |
ondrejmirtes
commented
Jan 30, 2022
No (https://phpstan.org/developing-extensions/dynamic-return-type-extensions):
|
@ondrejmirtes Thanks 👍 I'm trying to add JsonDecodeDynamicReturnTypeExtension, but the only function that is found is What I'm doing wrong there? |
| public function isFunctionSupported(FunctionReflection $functionReflection): bool | ||
| { | ||
| // @todo - finds only "assertType", but not "json_decode" :/ | ||
| dump($functionReflection->getName()); | ||
| return $functionReflection->getName() === 'json_decode'; | ||
| } |
There was a problem hiding this comment.
Here the json_decode is never passed :/
There was a problem hiding this comment.
Because there's already JsonThrowOnErrorDynamicReturnTypeExtension in phpstan-src whcih changes the result based on JSON_THROW_ON_ERROR. You need to modify it first.

By default, the
Nette\Utils\Json::decode()returns mixed, but in some cases we know there is more specific type.We use this extension internally in private project to separate at
arrayandstdClass, e.g.:It might be useful to have in Nette extension itself. What do you think?
cc @staabm@lulco@matthiasnoback
Based on https://twitter.com/VotrubaT/status/1487434178757074952