> On Sep 7, 2024, at 4:36 PM, Larry Garfield <la...@garfieldtech.com> 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

Reply via email to