-
Notifications
You must be signed in to change notification settings - Fork 680
feat: make key-of/value-of usable with non-const arrays #7396
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
feat: make key-of/value-of usable with non-const arrays #7396
Conversation
Converting to draft (just for easier maintenance) |
Do you have any idea how I can achieve the described case for |
I'm not sure I understood the issue exactly, but did you look at this:
using array_key_exists will generate an assertion The array here has int|string keys. You know $key is already a string. What will $key be after you array_key_exists? If you say key-of<$array>, you lost information about $key being a string. If you say string, you lost the information about $key being a valid offset. You'd need something like The type system is very complicated and I can only advise that you finish your first PR and all that will be related to it until you start on more |
I found these snippets: https://psalm.dev/r/e28860fd8a<?php
/**
* @template T of array<string|int, mixed>
* @param T $array
* @return key-of<T>|null
*/
function getKey(string $key, $array) {
if (array_key_exists($key, $array)) {
return $key;
}
return null;
}
|
Probably this case is something for later. I fixed all other outstanding issues, the original parsing for |
This will need to target the master branch, removing existing types is a big BC break. Also, can you fix the errors in shepherd before we review? It's possible you'll see issues that could have a big impact on your existing code. Reviewing is kinda hard, so I'd prefer doing that once everything is fixed! |
Okay, I will rebase to master, do you have some time schedule for the 5.x release? I'm not quite sure, if the latest shepherd issues are related to my changes. I'll have a look tomorrow. |
We don't have a release date yet for Psalm 5, we'll make sure to communicate when we will About the errors on shepherd, I'm pretty sure they're related to your changes. Upstream branch is clean and the errors seem consistent with what you changed |
I think I'm finally done rebasing to All failing tests/checks are also currently failing on the Ready for review now – hopefully 😅 FYI, I now no longer will force-push the branch, so that changes are transparent. |
there are errors in shepherd, they are related to a change in test format in master. We know require tests to be all associative arrays. Can you change the format of the tests you added? |
I already changed the format of my added tests, but there are tests in the my shepherd run: https://github.com/vimeo/psalm/runs/4859814032?check_suite_focus=true Same for the failing unit tests. |
sorry, this is actually my fault. I'm fixing that |
fixed :) Thanks for reporting, I forgot to check after the last merge |
Thanks! I just rebased 👍 |
Add tests for TValueOfArray.
Not in all cases the TemplateParam gets replaced before type checking, in these cases, use the defined `as` type. Refactor to extract key/value type of array union to method.
@orklah any idea how to pass this test here? <?php
/**
* @template TKey of int
* @template TArray of array<TKey, bool>
* @param TArray $array
* @return list<TKey>
*/
function toListOfKeys(array $array): array {
return array_keys($array);
} I have no idea why, but while debugging |
@AndrolGenhald sorry, this PR has already been 'exploded' a bit and took a lot of time, should be handled in a separate PR after this has been merged. |
I found these snippets: https://psalm.dev/r/3531bf3469<?php
class Foo
{
/** @var non-empty-list<int> */
public const BAZ = [1];
/** @return value-of<static::BAZ> */
public static function foobar(int $int): int
{
return static::BAZ[0];
}
}
|
Not sure what you mean, the snippet https://psalm.dev/r/d16778139e seems to work and return |
I found these snippets: https://psalm.dev/r/d16778139e<?php
/**
* @template TKey of int
* @template TArray of array<TKey, bool>
* @param TArray $array
* @return list<TKey>
*/
function toListOfKeys(array $array): array {
return array_keys($array);
}
$a = toListOfKeys([1 => 'a']);
/** @psalm-trace $a */;
|
Are you sure you ran it on my branch (commit
It's also already added as a test in |
This comment has been minimized.
This comment has been minimized.
I got it, I didn't implement |
Extend TTemplateKeyOf from Atomic instead of Scalar, to ensure it is only compared in AtomicTypeComparator to reduce duplicate code.
@orklah It's finally done – could you review again please? |
I'm ready to merge, no last change? :) |
Needs anything to be added to the |
Yeah, maybe document the change of inheritance |
I also added the renames as BCs. |
Thanks! |
Many thanks for your intensive and always fast review! 😊 |
Currently
key-of<T>
andvalue-of<T>
helper-types are only usable with class constants. But they can be even more powerful! This PR tries to add the following capabilites:array
-like types (includes keyed array, and lists), even with literalsT
-paramkey-of
, so that correctly not onlyarray-key
is checked, but instead only methods likearray_keys
can be used to ensure template support.value-of
which acceptsarray_values
if used correctly.Unfortunately
@psalm-assert-if-true
seems to not support template types, and even if I fix a bug insideFunctionLikeDocblockScanner
where template types aren't passed I have no success. So I welcome any suggestions to this! I saw that there is made use of assertions forarray-key-exists
but I didn't find how I can change the type of$key
so that this test won't fail: