[RFC] [Vote] Type Guards for Classes

php.internals

Patrik Václavek

2 years ago
Introduction ************* This RFC proposes a new feature in PHP: type guards for classes (or interfaces). This feature aims to simplify and standardize the process of verifying that a variable is an instance of a specific class, enhancing code readability and reducing boilerplate code. Motivation ************* Currently, in PHP, to ensure that a variable is an instance of a specific class, developers need to use the `instanceof` operator and manually throw an exception if the check fails. This results in repetitive boilerplate code scattered throughout the codebase. A new syntax, `(ClassName) $variable`, is proposed to streamline this process by performing an instanceof check and throwing a `TypeError` if the variable is not an instance of the specified class. Proposal *********** Introduce a new type guard syntax for classes: ```php (Foo) $variable; ``` This syntax will internally perform the following operations: 1. Check if `$variable` is an instance of `Foo`. 2. If the check fails, throw a `TypeError` with a message indicating the expected and actual types. Example: Consider the following class definition: ```php class Foo {    // class definition } ``` To ensure a variable is an instance of `Foo`, instead of writing: ```php if (!$variable instanceof Foo) {     throw new TypeError('Expected instance of Foo, got ' . gettype($ variable)); } ``` Developers can use the new type guard syntax: ```php (Foo) $variable; ``` Backward Compatibility *************************** This feature introduces new syntax and does not affect existing code. It is fully backward-compatible, as it does not modify or deprecate any existing functionality.

Benjamin Morel

2 years ago
On Thu, 16 May 2024 at 22:33, Patrik Václavek <PaTrOnY@email.cz> wrote:
> Introduction > ************* > > This RFC proposes a new feature in PHP: type guards for classes (or > interfaces). This feature aims to simplify and standardize the process of > verifying that a variable is an instance of a specific class, enhancing > code readability and reducing boilerplate code. >
Hi, please see this discussion: https://externals.io/message/105332 In particular this comment from Nikita: https://externals.io/message/105332#105348 That being said, I would still love it if we could find a way to get this feature, under this syntax or another, into PHP! - Ben

Ilija Tovilo

2 years ago
Hi Patrik On Thu, May 16, 2024 at 10:31 PM Patrik Václavek <PaTrOnY@email.cz> wrote:
> > Introduce a new type guard syntax for classes: > > ```php > (Foo) $variable; > ``` > > This syntax will internally perform the following operations: > > 1. Check if `$variable` is an instance of `Foo`. > 2. If the check fails, throw a `TypeError` with a message indicating the expected and actual types.
Note that this feature is covered under the pattern matching RFC with the "Throwing alternative" extension. https://wiki.php.net/rfc/pattern-matching#throwing_alternative In addition to just class types, it would support all other patterns, including scalar types, union types, array shapes, etc. Ilija

Larry Garfield

2 years ago
On Thu, May 16, 2024, at 3:31 PM, Patrik Václavek wrote:
> Introduction > ************* > > This RFC proposes a new feature in PHP: type guards for classes (or > interfaces). This feature aims to simplify and standardize the process > of verifying that a variable is an instance of a specific class, > enhancing code readability and reducing boilerplate code.
Without commenting on the idea itself, this is just a proposal at the moment. The subject line implies there's a formal RFC now up for a vote, when there is not even a formal RFC yet. Ie, please don't abuse the subject line incorrectly. :-) To comment on the idea itself, I believe Ilija is correct that using pattern matching would be the better approach here. Right now the RFC suggests $foo as <pattern> would return true or throw, but "return $foo or throw" would indeed make more sense. And then give us the entire power of pattern matching. (That RFC will come up formally soon(tm), I swear.) --Larry Garfield

Jordan LeDoux

2 years ago
On Thu, May 16, 2024 at 1:32 PM Patrik Václavek <PaTrOnY@email.cz> wrote:
> Introduction > ************* > > This RFC proposes a new feature in PHP: type guards for classes (or > interfaces). This feature aims to simplify and standardize the process of > verifying that a variable is an instance of a specific class, enhancing > code readability and reducing boilerplate code. > > Motivation > ************* > > Currently, in PHP, to ensure that a variable is an instance of a specific > class, developers need to use the `instanceof` operator and manually throw > an exception if the check fails. This results in repetitive boilerplate > code scattered throughout the codebase. A new syntax, `(ClassName) > $variable`, is proposed to streamline this process by performing an > instanceof check and throwing a `TypeError` if the variable is not an > instance of the specified class. > > Proposal > *********** > > Introduce a new type guard syntax for classes: > > ```php > (Foo) $variable; > ``` > > This syntax will internally perform the following operations: > > 1. Check if `$variable` is an instance of `Foo`. > 2. If the check fails, throw a `TypeError` with a message indicating the > expected and actual types. > > Example: > Consider the following class definition: > > ```php > class Foo { > // class definition > } > ``` > > To ensure a variable is an instance of `Foo`, instead of writing: > > ```php > if (!$variable instanceof Foo) { > throw new TypeError('Expected instance of Foo, got ' . > gettype($variable)); > } > ``` > > Developers can use the new type guard syntax: > > ```php > (Foo) $variable; > ``` > > Backward Compatibility > *************************** > > This feature introduces new syntax and does not affect existing code. It > is fully backward-compatible, as it does not modify or deprecate any > existing functionality. >
Since this throws, I'm struggling to understand how this would replace any usages of `instanceof` other than `if (!($var instanceof Foo)) throw new TypeError();` Also, this is not an RFC with a page I can look at OR something in a vote, so the subject line is a bit of a lie. But now that I've gotten my grumps out of the way, better class specific syntax is in general something that I think is positive and worth exploring. Jordan

Casper Langemeijer

2 years ago
On Thu, May 16, 2024, at 22:31, Patrik Václavek wrote:
> This feature aims to simplify and standardize the process of verifying that a variable is an instance of a specific class, enhancing code readability and reducing boilerplate code. > > Currently, in PHP, to ensure that a variable is an instance of a specific class, developers need to use the `instanceof` operator and manually throw an exception if the check fails. This results in repetitive boilerplate code scattered throughout the codebase. A new syntax, `(ClassName) $variable`, is proposed to streamline this process by performing an instanceof check and throwing a `TypeError` if the variable is not an instance of the specified class.
I view variables changing types to be an anti-pattern. Instead if adding type guards, I would rather see this problem solved by having typed local variables. This ensures that a variable always holds a specific type, avoiding the need of repetitive scattered type guards. Working with variables would then be the same as working with class properties. They could be typed or untyped. Also, I see the need for type guards as a symptom of bad composition. Mostly methods that are too large would benefit. If a method is decomposed into smaller methods the use of parameter and return type checks it's unlikely there is need for additional type guards.