Re: bikeshed: Typed Aliases

From: Date: Sat, 07 Sep 2024 20:36:44 +0000
Subject: Re: bikeshed: Typed Aliases
References: 1 2 3 4 5 6 7 8 9  Groups: php.internals 
Request: Send a blank email to internals+get-125474@lists.php.net to get a copy of this message
On Sat, Sep 7, 2024, at 12:07 PM, Rowan Tommins [IMSoP] wrote: > On 7 September 2024 17:23:13 BST, Davey Shafik <me@daveyshafik.com> wrote: >> >>My point is that if you talk about type DEFs, you now have this feature where you can input >>one type and get something that encapsulates it, and it seems weird that enums would LOOK similar In >>type hint usage and function differently. > > Personally, I would prefer to go the other way: make typedefs, like > enums, something you explicitly construct / cast to, rather than > something that implicitly coerces any compatible value. > > Like enums, I would want to use typedefs to prevent accidental mixing > of values (e.g. a name where a reference number was expected, or a size > in pixels where a size in centimetres was expected). That use is > compromised if every scalar value is silently accepted for any matching > typedef. > > Regards, > Rowan Tommins > [IMSoP] There's a couple of different use cases floating around close to each other here. One is a type *alias*, which is just "a way to type less." The other is a type *def*, which creates a new for-reals type that you can check at runtime. They are closely related, but serve different purposes. While an alias could make sense file-local or app-wide, in practice a def only makes sense app-wide. Whether we want to have one or the other or both is a subjective question. Personally I'd be fine with both, as I see them serving different purposes. eg: typealias Foo: Bar|Baz; Foo is now a compile time copy-paste for Bar|Baz, meaning this is totally valid: class A { public Foo $a; } class B { public Bar|Baz $a; } The other direction is: typedef UserId: int; UserID is now an object that consists of just an int, but can be type checked against. What's unclear is if you can do other int-y things to them (add, subtract, etc.), or if it's really just a shorthand for readonly class UserId { public function __construct(public int $value) {} } I could see an argument for either. If we had operator overloads, I would absolutely go for the latter; make all of those other int-y things opt-in. Once we get pattern matching, as noted a few months ago, it could be quite powerful to allow patterns as a validation on a typedef of that sort. typedef UserId: int is >0; Though that opens up all kinds of interesting questions about a typedef based on another typedef, if that's a form of inheritance or not, etc. Again, I'm not sure if Rob wants to go there or not, but it's a place my brain has gone before. :-) We may want to focus just on aliases for now, but design them in such a way that they do not cause an issue for typedefs in the future. (Eg, using the typealias keyword instead of just type.) --Larry Garfield

« previous php.internals (#125474) next »