Is there any "typed" type aliasing? Like regular <...
# server
h
Is there any "typed" type aliasing? Like regular https://kotlinlang.org/docs/type-aliases.html but that actually create new types but can be interchangeably assigned to from their underlying type?
Let's say I have a class `class FullName(val sirName: SurName, val name: Name)`and the two types of names would be like this
Copy code
typealias SirName: String
typealias Name: String
r
If they can be interchangeably assigned I don’t think I understand what aspect of them would make them differ from type aliases?
h
But I would like to use them as
FullName(sirName, name)
and if switch them around I get a compilation error because the types are different.
The idea would be that they would be strings whereever a string is expected and an alias where that is expected
Not sure it makes sense but I would like to type things a bit more tightly but not go all crazy with new "real" types 😮
e
use value classes? 🙂
h
I was looking at them but not sure it would work?
r
Got you. Unfortunately what you want does not exist.
value class Name(val value: String)
will give you the type safety but not the convenience -
Name
will not be a subtype of
String
, you’ll have to pass
Name.value
if you need a
String
.
h
Aha ok cool thanks!
r
Unless you drop into Java, where (most of the time…) your
Name
will actually be a
String
.
h
We are hard at work moving from Java and we have numerous Lombok generated things that become verbose a little brittle once the builders go
r
Sorry, what I was clumsily saying was that the point of a
value class
(rather than say a
data class
) is that it’s mostly optimised away at compile time so that the generated bytecode is the same as if you had just been using the type of its value (
String
in this case). Occasionally that’s not possible, so a “real”
Name
class is also generated and the value may sometimes be boxed as that.
h
I see interesting. I wish valhalla would be finished soon
j
You don't need Valhalla to benefit from Kotlin's value classes, as long as you need single-field value classes only
h
Yeah but we don't have any such candidate at the moment. We have several multiple field candidates however.
j
🤔 your example here has a 2-field class (
FullName
) that wants to use 2 single-field value classes. So you don't need Valhalla at all for this example:
Copy code
class FullName(val surName: SurName, val name: FirstName)

@JvmInline
value class SurName(val value: String)
@JvmInline
value class FirstName(val value: String)
The point of these value classes is to not be assignable to other types. So you can't give a
SurName
object where a
FirstName
is expected (this is the type safety benefit). As have been said before, conversely, with value classes you can't assign a plain string to a
SurName
nor assign a
SurName
to a plain string (unlike with type aliases), but this to me is also part of the point of using value classes. Conversions like this must be conscious/explicit. They are in fact independent types. So to create a
FullName
out of strings, you would need to write:
Copy code
val name = FullName(SurName("Lennon"), FirtName("John"))
r
I could see a certain amount of point in a
value class Name(val name : String)
being treated as a subtype of
String
- so you can’t use a
String
where a
Name
is needed, but you can use a
Name
where a
String
is needed. It would just be syntax sugar for
Name.name
, and at bytecode time it’s all just a
String
anyway. This would give (nearly?) all the advantages of type safety - a value class is a specialisation of the type of its value. But it would open up a whole bunch of issues around polymorphism. For instance, calling
Name("Jana").toString()
returns
Name(Jana)
. But pass
Name("Jana")
to a function that takes a
String
and calling
toString
on that
String
of course just returns
Jana
. Which totally breaks the expectation that they are (conceptually!) the same object. So all told, much cleaner and safer and less surprising if you have to explicitly dereference the wrapped property when its type is requested.
👍 1
(Tangent - I do slightly wish that
value class X(val value: T)
automatically generated
fun T.toX() = X(this)
- I so much prefer postfix conversion functions!)
h
Yeah I wasn't really suggesting the change just curious to see if there was already something that would help bring some more type safety to otherwise stringly typed things
👌 1
Thank you all for chiming in I learned a lot! 🙂
☺️ 1
j
@Rob Elliot indeed the "subtype of wrapped value" is an interesting consideration, but there are so many pitfalls with it (some of which you already mentioned) that I believe it would far outweigh the little benefit of not having to use
.value
. One other problem for instance is that
String
is supposed to be final, so it would be valid to expect that the runtime class of any variable of type
String
is in fact
String.class
, which would not be the case here if the value is boxed. Value classes don't guarantee that the inner value is always unboxed - at least that's the idea in Kotlin's value classes design. The goal is for the programmer to give up on identity so that the compiler is allowed to optimize this way (or in other ways), but nothing is really guaranteed (as you noted).