From d2300acafd3c77a5cf4430ee736b13fb21fb2d1e Mon Sep 17 00:00:00 2001 From: Gabriel Moraes Date: Wed, 1 Jul 2026 13:38:44 -0300 Subject: [PATCH] =?UTF-8?q?fix(phpstan):=20resolver=203=20erros=20n=C3=ADv?= =?UTF-8?q?el=208=20(SMSGoError::$code=20+=20Paginated=20generics)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SMSGoError::$code sobrescrevia Exception::$code como `readonly string`, o que o PHPStan (e o PHP 8.4) rejeitam ("readonly overrides readwrite" + tipo nativo sobre propriedade herdada sem tipo). Passa a ser declarada sem tipo nativo nem readonly, com o tipo string via PHPDoc; atribuída no construtor. - Paginated::fromArray() inferia self, divergindo do retorno condicional self|self. Ramos com/sem mapper separados p/ inferência correta. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/Model/Paginated.php | 21 ++++++++++++++++++--- src/SMSGoError.php | 15 ++++++++++++++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/Model/Paginated.php b/src/Model/Paginated.php index 86e43b9..78d0b41 100644 --- a/src/Model/Paginated.php +++ b/src/Model/Paginated.php @@ -39,14 +39,29 @@ public static function fromArray(array $payload, ?callable $mapItem = null): sel $rawMeta = is_array($payload['meta'] ?? null) ? $payload['meta'] : []; /** @var array $rawData */ $rawData = is_array($payload['data'] ?? null) ? $payload['data'] : []; + $meta = PaginationMeta::fromArray($rawMeta); - $items = []; + // Ramos separados para o PHPStan inferir o parâmetro genérico de cada + // caminho: self> sem mapper, self com mapper — + // batendo com o tipo de retorno condicional declarado acima. + if ($mapItem === null) { + $rows = []; + foreach ($rawData as $item) { + /** @var array $row */ + $row = is_array($item) ? $item : []; + $rows[] = $row; + } + + return new self($meta, $rows); + } + + $mapped = []; foreach ($rawData as $item) { /** @var array $row */ $row = is_array($item) ? $item : []; - $items[] = $mapItem !== null ? $mapItem($row) : $row; + $mapped[] = $mapItem($row); } - return new self(PaginationMeta::fromArray($rawMeta), $items); + return new self($meta, $mapped); } } diff --git a/src/SMSGoError.php b/src/SMSGoError.php index ffd56a3..5863773 100644 --- a/src/SMSGoError.php +++ b/src/SMSGoError.php @@ -18,6 +18,18 @@ */ final class SMSGoError extends RuntimeException { + /** + * Código estável do erro (ex.: `validation_error`, `insufficient_balance`). + * + * Sobrescreve `Exception::$code` (herdada sem tipo nativo e readwrite), por + * isso é declarada aqui **sem tipo nativo e sem `readonly`** — do contrário o + * PHP/PHPStan acusam "readonly overrides readwrite" e "should not have a + * native type". O tipo real é `string`, definido via PHPDoc. + * + * @var string + */ + public $code; // phpcs:ignore SlevomatCodingStandard.TypeHints.PropertyTypeHint + /** * @param int $status Status HTTP (0 em falha de rede/transporte). * @param string $code Código estável do erro. @@ -27,10 +39,11 @@ final class SMSGoError extends RuntimeException public function __construct( string $message, public readonly int $status, - public readonly string $code, + string $code, public readonly mixed $details = null, public readonly ?array $errors = null, ) { parent::__construct($message); + $this->code = $code; } }