A user-defined value type is defined using type C is V, where C is the name of the newly introduced type and V has to be a built-in value type (the “underlying type”). The function C.wrap is used to convert from the underlying type to the custom type. Similarly, the function C.unwrap is used to convert from the custom type to the underlying type.
The type C does not have any operators or attached member functions. In particular, even the operator == is not defined. Explicit and implicit conversions to and from other types are disallowed.
Why is it designed this way?
Why don’t design the keyword Type’s function just as a pure alias function like the keyword Typedef’s function in C++?
Just make compopiler do replace for us, they are equal.
It could be that way but personally as a Solidity dev I like that it’s not. The main use I have for this is to leverage the type system to check different things in my code like state transitions, correct use of units / denominations and to define custom memory data structures
One example the project I’m working on currently is that I have 3 aliases of uint256 that are PriceAB, AmountA and AmountB. While they are all uint256 under the hood the fact that they’re treated as different types lets me define two separate convert(PriceAB price, AmountA amount) returns (AmountB) and convert(PriceAB price, AmountB amount) returns (AmountA) methods.
This is especially useful in my case for price conversions as it was very error-prone to know and keep track of what variable was denominated in what token just from names. Using custom types I could rely on Solidity’s type system to do some of the checking for me.
Another use for this is when I have custom in-memory data structures where the type aliases uint256 but represents a pointer or packed pointer + length. I definitely wouldn’t want me accidentally manipulating a normal uint as such a data structure.
Also note that in certain contexts they are treated the same for instance for the ABI and external contracts custom type inputs are treated as the underlying type.
Hopefully once generics are introduced we can have both in Solidity, I definitely agree there are some cases where them being treated equally could be helpful although at that point you may as well use the base type.