【tech blog EN→JP】PHP needs an "unknown" type

PHP needs an "unknown" type (PHPには「unknown型」が必要だ)
なんか気になったので翻訳しつつ、個人の所感や調査内容を添えつつ記事化してみる試み。

Typescriptのunknown型について
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.
もしあなたがTypescriptに慣れ親しんで知るのなら、TSにおけるany型のことはご存知かもしれません。anyを使って何かしらの実装を行うことができますね。
それは実際の型についてのあなたは何も分からず、実装においてなんでもあり状態であることの証左です。
以下のコードは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.
typescript3.0において unknown型
が発表されました。unknownはanyと似ているようで全く異なる使われ方をされます。
(anyと同様に)unknownもまたどのような値にもなり得ますが、そのようなunknown型変数が使用されるというのは理屈が裏返ってしまうことを意味します。
- anyでは変数にどのような値が代入されようと許容されます。私たちはその値が何者であるか分からないからですね。
- unknownではあらゆる型の値を許容しません。(同様の理由になりますが)私たちはその値が何者であるか分からないからです。
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
}
📝: その値の型が何なのか分からないが故にanyは全てを受け入れ・一方unknownは一切を受け入れない

一方その頃PHPは
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.
PHPでは、anyもunknownも持たない代わりにmixedという型があります。mixedはPHP8.0以降のバージョンで公式な型として扱われることになりました。そして静的解析ツールを使用した際の結果もmixedとされます。
参考
※ここでいうmixedは array|bool|callable|int|float|null|object|resource|string
と等価という意味
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.
もし次のコードをPHPStanでチェックを行ったとしてエラーは発生しないでしょう。Psalmではlevel2ではエラー無し、level1ではエラーが発生します。
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.
PHPにunknown型が実装されていれば、これら静的解析ツールと同じ動作(型検査)ができた可能性があります。mixed型に変更を加えるということは大きなBCブレイク(後方互換性がないことによる破壊的変更)をもたらすことになり、それは多くのmixedが存在しているレガシープロジェクトでは尚更でしょう。
unknown型はPHP自体に型として組み込むべきではないのかもしれません、しかしアノテーションとして存在させることは出来るかもしれません。
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.
unknown型があれば、開発者は(型の)厳密性レベルを下げた状態で(静的解析ツールの)機能を扱うことができるようになります。ベースラインファイルに何千ものignore指定を追加する必要もなくなりますしね。

所感
-
Typescriptにおける
any
とunknown
の概念・考え方について
→ その値の型が何なのか分からないが故にanyは全てを受け入れ・一方unknownは一切を受け入れない -
PHPにunknown型を入れ込むのは難しそう、からの
しかしアノテーションとして存在させることは出来るかもしれません。
→ あくまでPHPDoc上で開発者の意図を他開発者に明示的に示すためのもの、くらいの使い方?