Psalm possibly null value provided with request->get()

3.2k views Asked by At

I have the following code:

$request->headers->get('Accept-Language', 'en');

I provide a default value but Psalm thinks it's potentially null since ->get() declares that return a nullable string:

// vendor/symfony/http-foundation/HeaderBag.php
/**
 * Returns a header value by name.
 *
 * @return string|null The first header value or default value
 */
public function get(string $key, string $default = null) { /* */ }

How can I fix this so psalm knows it's not null?

2

There are 2 answers

0
yivi On

Since you cannot control the annotation in the upstream library, you'll have to provide the missing information to Psalm in your own code.

A couple of ways to go about it:

Cast to string, so Psalm has no doubt what type get() is getting you:

$a = (string) $request->headers->get('Accept-Language', 'en');

Yup, the cast is redundant, but it's clear and concise. I usually do this just for economy.

You could explicitly declare that the variable that result of this get() call is a string:

/** @var string $acceptLanguage **/
$acceptLanguage = $request->headers->get('Accept-Language', 'en');

Finally, you can simply suppress the PossiblyNullArgument wherever you need it:

/** @psalm-suppress PossiblyNullArgument */
iWantAString($request->headers->get('Accept-Language', 'en'));

See all these working here.

You can also combine some of the above with your own wrapper method to deal with getting values from the request, making sure you always return string. If you do that, you should probably throw an exception if the parameter is not found.

0
weirdan On

In addition to @yivi's answer that shows you how you can override type inference or suppress the error, you can also explain the type to Psalm by providing correct docblock using conditional types either directly in the source code (if you have control over that) or in a stub file.

/**
 * Returns a header value by name.
 *
 * @psalm-return ($default is null ? (string|null) : string)
 */
public function get(string $key, string $default = null) { /* */ }

https://psalm.dev/r/41b8471847