这可能很难描述,这就是为什么我正在努力寻找匹配的答案。
<?php
declare(strict_types=1);
/**
* @template T of object{'a': string, 'b': int, 'c': DateTime}
*/
class Foo {
/**
* @var object<T>
*/
private object $foo;
// Assume __construct populates the $foo property
/**
* @param key-of<T> doesn't seem to apply here - only applies
* to catching keys that aren't in T
*
* @return ??? indicate $key is a property of T, so return is that property's type
*/
public function get(string $key)
{
return $this->foo->{$a};
}
}
function string_only(string $a): string { return $a; }
function integer_only(int $b): int { return $b; }
// How do I know what was returned?
$a = (new Foo)->get('a');
// $a should be treated as string by code analysis
string_only($a); // OK
integer_only($a); // Inspection type warning
$b = (new Foo)->get('b');
// $b should be treated as int by code analysis
string_only($b); // Inspection type warning
integer_only($b); // OK
$c = (new Foo)->get('c');
// Code completion should know I can do this
$c->format('Ymd');
PhpStorm各种尝试的检查结果:
// @return T<$key>
// @return T{$key}
string_only($a); // "Return value must be of type 'string', 'object' returned"
// @return T->$key
string_only($a); // "Return value must be of type 'string', 'T-' returned"
各种其他尝试不被识别为任何东西或给出类似于上面的内容。
可以使用任何当前的 PHP SA 工具来完成此操作吗?
我在
@return
注释中尝试了各种模式,但检查要么根本无法识别它们,要么表明函数返回一个对象而不是对象键的类型。
我希望静态分析工具能够理解
$key
的值代表 T
对象的属性。
Primero,需要纠正错误。例如,在您的方法中,使用 $key 和 $a 来使用。
继续使用 @psalm-param 和 @psalm-return 来恢复参数值。
有一个可能的解决方案:
php
Copy code
declare(strict_types=1);
/**
* @template T of array{'a': string, 'b': int, 'c': DateTime}
*/
class Foo {
/**
* @var T
*/
private array $foo;
// Supongamos que __construct llena la propiedad $foo
/**
* @psalm-param key-of<T> $key
* @psalm-return T[$key]
*/
public function get(string $key)
{
return $this->foo[$key];
}
}
Usando @psalm-param key-of $key, estás diciendo que el valor de $key debe ser una de las claves del tipo T.
Usando @psalm-return T[$key], estás diciendo que el Tipo de retorno debe ser el tipo del valor counteriente a la clave $key en T.
Con estas anotaciones,诗篇 debería ser capaz de inferir que:
(new Foo)->get('a') devuelve un string.
(new Foo)->get('b') devuelve un int.
(new Foo)->get('c') devuelve un DateTime.