阅读PHP/Hack中的嵌套词典



我正在尝试一个简单的嵌套字典,然后读取一个嵌套值

$response = dict[
'some_other_key' => 'asdf',
'sub_response' => dict['success' => false],
];
if ($response['sub_response']['success']){
// do stuff
}

我被这个错误弄糊涂了:

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.

它似乎读错了键,并抱怨这是一根绳子?我做错了什么?

在Hack中,字典的每个键和每个值都有相同的类型;对于不均匀的用例,形状可能更合适。换句话说,字典很适合将一堆用户ID映射到相应的用户对象(dict<int, User>(——这是一组统一的映射,但你不知道键的数量或具体是什么,其中您提前知道您拥有哪些密钥(some_other_keysub_response(,因此类型检查器可以跟踪每个密钥的类型。

文件中提到了这一点,尽管它被掩盖了,也不清楚IMO:

如果您希望不同的关键点具有不同的值类型,或者如果您想要一组固定的关键点,请考虑使用形状。

所以这里发生的是,类型检查器试图推断$response的类型。当然,它们的键是string,但它确实对值感到困惑。有时您将其用作dict<string, string>,有时用作dict<string, dict<string, bool>>——这是不允许的。

尽管这段代码确实有错误,但消息非常令人困惑(可能值得提交一个bug(。我认为你是对的,类型检查器认为$response['sub_response']必须是字符串,所以['success']无效?但奇怪的是,它不会为$response推断出dict<string, mixed>的类型——这是$response的有效类型,尽管仍然不是您想要的,但它可能会给出更好的错误消息。

在任何情况下,您似乎想要的是一个形状,其中每个单独键的类型都被单独跟踪。这是你想要的,我认为:

$response = shape(
'some_other_key' => 'asdf',
'sub_response' => dict['success' => false],
);
if ($response['sub_response']['success']){
// do stuff
}

(您可能还希望sub_response是一种形状,这取决于您最终使用它的方式。(

最新更新