@phpstan-type / @psalm-type bind a short name to a complex shape on the
declaring class. Analyzers that expand the alias reject a missing required
key when the alias is used as a @param type.
References:
- PHPStan phpdoc-types: Local type aliases
- Psalm utility_types.md: Type aliases| Analyzer | Version | Result | Diagnostics |
|---|---|---|---|
| phan | 6.0.7Phan 6.0.7 php-ast version 1.1.3 PHP version used to run Phan: 8.5.9 | Unrecognized | aliases_local_type.php:28: Parameter $address has undeclared type \Conformance\Tests\AliasesLocalType\UserAddress [PhanUndeclaredTypeParameter]
aliases_local_type.php:37: Argument 1 ($address) is ['street'=>'1 Main St','city'=>'Town','zip'=>'12345'] of type array{street:'1 Main St',city:'Town',zip:'12345'} but \Conformance\Tests\AliasesLocalType\User::setAddress() takes \Conformance\Tests\AliasesLocalType\UserAddress (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/aliases_local_type.php:28 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]
aliases_local_type.php:40: Argument 1 ($address) is ['street'=>'1 Main St','city'=>'Town'] of type array{street:'1 Main St',city:'Town'} but \Conformance\Tests\AliasesLocalType\User::setAddress() takes \Conformance\Tests\AliasesLocalType\UserAddress (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/aliases_local_type.php:28 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]
Expectation diffLine 37: Expected valid value to be accepted, got ["Argument 1 ($address) is ['street'=>'1 Main St','city'=>'Town','zip'=>'12345'] of type array{street:'1 Main St',city:'Town',zip:'12345'} but \\Conformance\\Tests\\AliasesLocalType\\User::setAddress() takes \\Conformance\\Tests\\AliasesLocalType\\UserAddress (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/aliases_local_type.php:28 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]"] |
| phpstan | 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 | Enforced reported Lv.5+ | aliases_local_type.php:40: Parameter #1 $address of method Conformance\Tests\AliasesLocalType\User::setAddress() expects array{street: string, city: string, zip: string}, array{street: '1 Main St', city: 'Town'} given. [identifier=argument.type] [reported-from-level=5]With strict-rulesaliases_local_type.php:40: Parameter #1 $address of method Conformance\Tests\AliasesLocalType\User::setAddress() expects array{street: string, city: string, zip: string}, array{street: '1 Main St', city: 'Town'} given. [identifier=argument.type]
|
| psalm | 6.16.1Psalm 6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac next: 7.0.0-beta19 |
Enforced | aliases_local_type.php:40: Argument 1 of Conformance\Tests\AliasesLocalType\User::setAddress expects array{city: string, street: string, zip: string}, but array{city: 'Town', street: '1 Main St'} provided [InvalidArgument]
|
| mago | 1.46.0mago 1.46.0 | Enforced | aliases_local_type.php:40: Possible argument type mismatch for argument #1 of `Conformance\Tests\AliasesLocalType\User::setAddress`: expected `array{'city': string, 'street': string, 'zip': string}`, but possibly received `array{'city': string('Town'), 'street': string('1 Main St')}`. [possibly-invalid-argument]
|
| mir | 0.70.1mir 0.70.1 | Enforced | aliases_local_type.php:40: InvalidArgument: Argument $address of setAddress() expects 'array{'street': string, 'city': string, 'zip': string}', got 'array{'street': "1 Main St", 'city': "Town"}' [MIR0201]
|
| phpantom | 0.9.0phpantom_lsp 0.9.0 | Not enforced | No diagnostics reported.
|
| intelephense | 1.18.5intelephense 1.18.5 | Not enforced | No diagnostics reported.
|
| phpy | 0.2.0phpy 0.2.0 | Not enforced | No diagnostics reported.
|
| qodana | 262.8665.325Qodana 262.8665.325 | Enforced | aliases_local_type.php:40: Incomplete array according to shape declaration. Missing key(s): zip [PhpMissingArrayKeyInspection]
|
| noverify | 0.5.5NoVerify, version 0.5.5: built on: 2025.04.22 14:36:46 OS: r-kuchinskas arm64 Commit: 4774b82f8adc53fbef38f95e97af4b953b4d1529 | Unrecognized | aliases_local_type.php:26: Class or interface named \Conformance\Tests\AliasesLocalType\UserAddress does not exist [undefinedClass]
|
| steins | 0.1.5steins 0.1.5 (2026-08-12 revision 39b4cc1) | Not enforced | No diagnostics reported.
|
| phpstan-strict | 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 | Enforced | aliases_local_type.php:40: Parameter #1 $address of method Conformance\Tests\AliasesLocalType\User::setAddress() expects array{street: string, city: string, zip: string}, array{street: '1 Main St', city: 'Town'} given. [identifier=argument.type]
|
| psalm-next | 7.0.0-beta19Psalm 7.0.0-beta19@7e751c06a756fa64dc4c759c09fe4a173afcb433 | Enforced | aliases_local_type.php:40: Argument 1 of Conformance\Tests\AliasesLocalType\User::setAddress expects array{city: string, street: string, zip: string}, but array{city: 'Town', street: '1 Main St'} provided [InvalidArgument]
|
<?php
declare(strict_types=1);
namespace Conformance\Tests\AliasesLocalType;
/**
* Local type aliases via vendor-prefixed annotations.
*
* `@phpstan-type` / `@psalm-type` bind a short name to a complex shape on the
* declaring class. Analyzers that expand the alias reject a missing required
* key when the alias is used as a `@param` type.
*
* References:
* - PHPStan phpdoc-types: Local type aliases
* - Psalm utility_types.md: Type aliases
*/
/**
* @phpstan-type UserAddress array{street: string, city: string, zip: string}
* @psalm-type UserAddress = array{street: string, city: string, zip: string}
*/
final class User // T: @phpstan-type / @psalm-type
{
/**
* @param UserAddress $address
*/
public function setAddress($address): void // T: UserAddress
{
}
}
$user = new User();
// Valid complete shape — tools that model the alias accept. An analyzer that
// treats the alias as a class name rejects this too (incidental, not enforcement).
$user->setAddress(['street' => '1 Main St', 'city' => 'Town', 'zip' => '12345']); // V
// Missing required key `zip` — alias expansion should reject this shape.
$user->setAddress(['street' => '1 Main St', 'city' => 'Town']); // E?: incomplete UserAddress shape should be rejected