PHPStan 转换为更具体的数组形状

bie*_*era 5 phpstan array-shape

在我的代码中,我调用一个方法,其返回值的类型如下:

/**
 * @return array<int, array<string,mixed>>
 */
public function fetchAllAssociative(): array;
Run Code Online (Sandbox Code Playgroud)

子类型array<string, mixed>以通用方式描述数据库记录。我确切地知道这个数据库记录是什么样的,所以我想更具体地记录该方法:

/**
 * @return array<int, array{id: int, firstName: string, lastName: string}>
 */
public function getAllUsers(): array
{
  return $this->userRepository->fetchAllAssociative();
}
Run Code Online (Sandbox Code Playgroud)

然而,PHPStan 抱怨说我应该完全按照以下方式键入我的方法fetchAllAssociative

Method UserRepository::getAllUsers() should return array<int, array{id: int, firstName: string, lastName: string}> but returns array<int, array<string, mixed>>.

有办法投吗?我的解决方法是引入一个新变量并使用@var标签,但我不太喜欢它(其他静态代码分析工具也不喜欢它)

/**
 * @return array<int, array{id: int, firstName: string, lastName: string}>
 */
public function getAllUsers(): array
{
  /**
   * @var array<int, array{id: int, firstName: string, lastName: string}> $data
   */
  $data = $this->userRepository->fetchAllAssociative();

  return $data;
}
Run Code Online (Sandbox Code Playgroud)

Wat*_*cle 0

我遇到了类似的事情。不幸的是,我认为添加// @phpstan-ignore-next-line到实现中是您唯一可以做的其他事情。

在 Typescript 中,这基本上等同于断言anyis User。通常,当您获取并验证数据(例如来自数据库或 http 请求)时,这会在“makeUser”函​​数中发生,以便您可以最大限度地减少使用data as unknown as User量。不然就是这个后果。

因此,一般建议其他遇到这种情况的人,从您的存储库开始,真正避免使用array<mixed>mixed,因为它会很快渗透到您的系统中。