Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code comment that asserts a variable satisfies a type (@psalm-satisfies) #10893

Open
annervisser opened this issue Apr 10, 2024 · 2 comments
Open

Comments

@annervisser
Copy link
Contributor

Feature request: @psalm-satisfies comment annotation

Problem

It can be useful for multiple reasons to annotate the type of a variable
that psalm already knows the type of:

  • Readability for other developers without them grokking complex return types
  • Helping IDEs understand the types of variables (for cases where PHPStorm is not as smart as psalm)
  • As a replacement for runtime checks that prevent bugs from code changes elsewhere

Currently this can only be done by using @var or @psalm-var comments.
But these tags are unsafe: Psalm treats those as gospel, and assumes whatever you
put in them to be true.

Solution

I propose a new tag that specifies the type of a variable, but that
Psalm actually verifies is correct. This would allow expressing type
expectations in code.

Example:

/**
 * @psalm-return ($asList is true ? list<string> : array<string, string>)
 */
function getItems(bool $asList): array
{
    $arr = ['a' => 'item', 'another' => 'item'];
    return $asList ? array_values($arr) : $arr;
}

$a = getItems(true);
/** @psalm-satisfies list<string> $a */
// From here on out anyone reading can safely assume that $a is list<string>
// And with a bit of luck PhpStorm could start interpreting psalm-satisfies the same as a @var tag
Problems
  • For this to be useful for IDEs, they would have to explicitly add support for this tag.
    • PHPStorm already has support for a lot of Psalm's annotations, so it might add support if this is implemented.
    • An alternative syntax re-using the @var annotation could also be considered, see Alternatives below

Alternatives

  • It might be more consistent to allow inline @psalm-assert $variable instead of introducing a new tag.
  • To work with IDEs out of the box, the @var tag could be re-used:
    • Perhaps a differentiation between @var and @psalm-var
    • Or a way to mark a @var as an assert: /** @var list<string> $myVar !assert */
Copy link

I found these snippets:

https://psalm.dev/r/721c3dae1b
<?php
	/**
	 * @psalm-return ($asList is true ? list<string> : array<string, string>)
	 */
 function getItems(bool $asList): array
	{
		$arr = ['a' => 'item', 'another' => 'item'];
		return $asList ? array_values($arr) : $arr;
	}

$a = getItems(true);
/** @psalm-satisfies list<string> $a */
// From here on out I know that $a is list<string>
// And with a bit of luck PhpStorm could start interpreting psalm-satisfies the same as a @var tag
Psalm output (using commit ef3b018):

ERROR: InvalidDocblock - 14:99 - Unrecognised annotation @psalm-satisfies

INFO: UnusedVariable - 11:1 - $a is never referenced or the value is not used

@danog
Copy link
Collaborator

danog commented Apr 11, 2024

See #10577 for the WIP implementation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants