PHP singleton type documentation says little about the false type and true type (both are also considered singleton types).
Could anybody please explain why does:
function myFunction(): false
{
return 1 < 0;
}
$result = myFunction();
var_dump($result);
Return bool(false) and not something like false(false) or singleton(false)?
This is quite frustrating because since the documentation doesn't specify whether false type and true type are return-only types or value types, I expected them to be value types, meaning creating a variable of this type should be valid, which turns out not to be the case.
PHP singleton type documentation says little about the false type and true type (both are also considered singleton types).
Could anybody please explain why does:
function myFunction(): false
{
return 1 < 0;
}
$result = myFunction();
var_dump($result);
Return bool(false) and not something like false(false) or singleton(false)?
This is quite frustrating because since the documentation doesn't specify whether false type and true type are return-only types or value types, I expected them to be value types, meaning creating a variable of this type should be valid, which turns out not to be the case.
Share Improve this question edited Feb 15 at 14:50 rozsazoltan 8,2755 gold badges18 silver badges38 bronze badges asked Feb 15 at 12:08 RedgardRedgard 396 bronze badges 5 |2 Answers
Reset to default 3The first thing to clarify here is that types in declarations are primarily assertions: when you say function foo(): SomeType
you are telling PHP to throw an error if the function tries to return anything other than SomeType
. There are cases where PHP will coerce the result type, and only throw an error if the coercion fails, such as turning the integer 1 into the float 1.0; but if the value returned is already an acceptable type, it will be left alone.
The second thing to clarify is that the syntax for specifying what types are accepted is richer than the set of types which a value can hold. For instance, it includes "union types" like string|int
which means "any string or any integer"; you can't have a value of type string|int
, but you can look at a value and see if it matches that constraint.
Putting these together, the role of true
and false
in type declarations becomes clearer: they are not describing new types in the language, they are just questions you can ask about a variable. The original motivation was to document the calling convention of existing functions such as strpos "returns the location as an integer on success, boolean false on failure". You could mark that as returning int|bool
, but since it never returns true
, specifying int|false
is more precise. That doesn't mean false
is a new type, it just means that if the function tried to return true
, the engine could throw an error that "true
does not meet the constraint int|false
".
The ability to specify true
in the same place was actually added later, to make things more complete and consistent. The labelling of these as "singleton types" is just a theoretical description of how different types relate to each other - false
is a sub-type of bool
in the same way that DateTimeImmutable
is a sub-type of DateTimeInterface
. Note that these "singleton types" are not constrained to use only in return types, they can for instance be used in the type of a property with exactly the same meaning.
<?php declare(strict_types=1);
class Foo {
public int|false $bar;
}
$foo = new Foo;
$foo->bar = 42; // OK
$foo->bar = false; // OK
$foo->bar = true; // TypeError: Cannot assign true to property Foo::$bar of type int|false
At first glance, it might seem pointless to specify true
or false
outside a union type, but it might be useful with polymorphism: if an interface says that a method must return int|false
, it is allowed for an implementation to say it only ever returns int
, or that it only ever returns false
. Similarly, an interface might specify a return type of bool
, but an implementation wants to document that it only ever returns true
- a valid boolean, but a more specific constraint.
It can only return the false
value, but the value itself still belongs to the bool
type.
Singleton types are those which allow only one value.
- Singleton types
So the false
singleton type only accepts the result bool(false)
, while for the true
singleton type, the expected return value will only be bool(true)
. This is especially useful when we want to tighten a inherited function that already returns a bool
result.
false
but rejectstrue
: 3v4l./WWcEk – IMSoP Commented Feb 15 at 13:07true
andfalse
as types, and considers them sub-types of the typebool
. Compare OO types: any instance of a particular interface will also be an instance of some concrete class, but we can still accurately call the interface a type. – IMSoP Commented Feb 15 at 14:44