I'm trying to have a simple nested dictionary, and then read a nested value
$response = dict[
'some_other_key' => 'asdf',
'sub_response' => dict['success' => false],
];
if ($response['sub_response']['success']){
// do stuff
}
I am so confused by this error:
Typing[4324] Invalid index type for this array [1]
-> Expected int [2]
-> This can only be indexed with integers [3]
-> But got string [2]
40 |
41 | $response = dict[
[3] 42 | 'some_other_key' => 'asdf',
43 | 'sub_response' => dict['success' => false],
44 | ];
45 |
[1,2] 46 | if ($response['sub_response']['success']) {
47 | return $response;
48 | }
1 error found.
It seems like it's reading the wrong key and complaining that it's a string? What am I doing wrong?
In Hack, a dictionary has the same type for every key and every value; for non-uniform use-cases a shape is probably more appropriate. In other words, dictionaries are good for things like mapping a bunch of user IDs to their corresponding user object (
dict<int, User>) -- it's a uniform set of mappings, but you don't know ahead of time how many or what exactly the keys will be. A shape is better for cases like this, where you know ahead of time what keys you have (some_other_key,sub_response) and so the typechecker can track a type for each individual key.The documentation mentions this, though it's pretty buried and unclear IMO:
So what's happening here is that the typechecker is trying to infer a type for
$response. They keys arestring, sure, but it's indeed getting confused about the values. Sometimes you use it as adict<string, string>and sometimes as adict<string, dict<string, bool>>-- which is not allowed.Even though this code is indeed in error, the message is extremely confusing (to the point it might be worth filing a bug). I think you are right that the typechecker is thinking that
$response['sub_response']must be a string and so['success']is invalid? But that's weird that it wouldn't infer a type ofdict<string, mixed>for$response-- which is a valid type for$response, though still not what you wanted, but it would probably give a better error message.In any event, what you seem to want here is a shape, where the type of each individual key is tracked separately. This does what you want, I think:
(You may also want
sub_responseto be a shape, depending on how you ultimately use it.)