A function returning an associative array returns array as far as any type system is concerned, so nothing can check the keys. A docblock with a shape gives the analyser the structure the language cannot express.
/**
* @return array{sku: string, price: int, in_stock: bool}
*/
public function summarise(Product $product): array
{
return [
'sku' => $product->sku(),
'price' => $product->price()->cents(),
'in_stock' => $product->inStock(),
];
}
A typo in a key at the call site becomes an error rather than a null. It is a docblock, so the engine ignores it entirely — which is the trade: the check exists in CI and not at runtime. The honest observation is that a shape complicated enough to need this annotation is usually asking to be a small value object instead.