> On Sep 7, 2024, at 4:36 PM, Larry Garfield <[email protected]> wrote:
>
> 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
Referencing prior art (e.g. Go) PHP could allow int literals — e.g. `1`, `47`,
etc. — to be passed to typedefs derived from ints but require int variables to
be typecast to the required type. Same for string literals.
In Go you cannot add or subtract on a typedef without casting to the underlying
type. I would definitely prefer that to be relaxed, but only if it is relaxed
via an explicit opt-in, e.g. something maybe like this:
typedef UserId: int operations: +, -, *, /;
typedef UserName: string operations: .;
Or less cryptic:
typedef UserId: int operations: add, subtract, multiply, divide;
typedef UserName: string operations: concat;
Going with the named operations would allow other operations to be opt-in in
the future, but would call into question defining operations as a first-class
language element.
> readonly class UserId {
> public function __construct(public int $value) {}
> }
>
> I could see an argument for either.
Typedefs enable a developer to write more robust code that they currently
cannot do, whereas typealiases are really just syntax sugar, albeit sugar that
probably tastes really good.
Said more explicitly, I would prefer both but if it is has to be only one to
start, I would prefer starting with typedefs.
> 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. :-)
Given that a typedef can always just reference the original type(s) rather than
basing a typedef on another typedef I would err on the conservative side and
say initially no typedef of a typedef.
The current downside would be that a complex union typedef defined in one
namespace could not easily be referred to in another namespace without
repeating the union typedef. Whether that would become a frequent problem
remains to be seen so it could wait for a future RFC if so.
Another limit would to the workaround would be if a typedef is defined as
private for a namespace. This as namespace-private is not currently possible we
could cross that typedef-on-a-typedef bridge on a future day if
namespace-private ever becomes possible. #jmtcw
> 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`.)
Another option is to use a different syntax:
type MyNewType: Foo
type MyAlias = Foo
Not arguing for or against any specific syntax, just pointing out that there
are other potential options.
-Mike