PHP needs an "unknown" type

May 21, 2021·
Gert de Pagter
Gert de Pagter
· 2 min read

If you are familiar with Typescript, you may know their any type. With any you can do anything. It signals that you don’t know about the actual type, and that anything goes. The following code is completely valid in Typescript.

const doTheThing = (input: any) => {
  input + input;
  input.toString();

  Object.keys(input).map((key) => {
    return input.foo[key];
  });

  const [one, two] = input;
  input();
}

In Typescript 3.0 the unknown type was introduced. unknown is both like any, and completely different. unknown also means that it can be any value, but the logic about it is inverted. With any, anything is allowed, because we don’t know what it is. With unknown, nothing is allowed, because we don’t know what it is.

const doTheThing = (input: unknown) => {
  input + input; // error
  input.toString(); // error

  Object.keys(input).map((key) => { // error
    return input.foo[key]; // error
  });

  const [one, two] = input; // error
  input(); // error
}

In PHP we have don’t have any or unknown, instead we have mixed. Which is an official type since PHP 8.0. And when using static analysis tools the results are mixed.

If we take the following piece of code, and check it with PHPStan, we get no errors. With Psalm we don’t get any errors on level 2, but on level 1 we do.

function doTheThing(mixed $input): void {
	$input->toString();
	$keys = array_keys($input);	
	[$one, $two] = $input;
	$input();
}

If PHP would have an unknown type, then it could have the same behavior with both tools. Making changes to mixed would be a big BC break, especially for legacy projects where there is a lot of that. Unknown wouldn’t be a type that should be in PHP itself, but it could live as an annotation.

If we have unknown, we can allow users to use the feature on lower strictness levels. It would also prevent them from having to add potentially thousands of ignores to a baseline file.