Default Types for Generics

Here’s one case where I would like to use default types for generics:

fun <TId> item(lambda: DlgTextItemDef<TId>.() -> Unit) = 
   DlgTextItemDef.build(lambda)

In my scenario it is very common that items have no id, but I have to write item<Unit> everywhere. I tried with an overload:

fun item(lambda: DlgTextItemDef<Unit>.() -> Unit) =
   DlgTextItemDef.build(lambda)

fun <TId> item(lambda: DlgTextItemDef<TId>.() -> Unit) = 
   DlgTextItemDef.build(lambda)

This does not compile, because it generates a naming clash on the JVM. I tried inlining it, but the compiler still complains:

inline fun <reified Id> item(noinline lambda: DlgTextItemDef<Id>.() -> Unit) =
   DlgTextItemDef.build(lambda)

This forces me to either be happy with item<Unit>, or use a different name for the rare use case, i.e. itemWithId. But the latter is ugly, because there are already overloads:

fun <Id> item(lambda: DlgTextItemDef<Id>.() -> Unit) =
    DlgTextItemDef.build(lambda)

fun <Id> itemWithBooleanValue(lambda: DlgBooleanItemDef<Id>.() -> Unit) =
    DlgBooleanItemDef.build(lambda)

fun <Id> itemWithIntValue(lambda: DlgIntItemDef<Id>.() -> Unit) =
    DlgIntItemDef.build(lambda)

fun <Id> itemWithFloatValue(lambda: DlgFloatItemDef<Id>.() -> Unit) =
    DlgFloatItemDef.build(lambda)

So I would end up with itemWithBooleanValue, itemWithBooleanValueWithId, etc. Clearly, the following would be the best solution:

fun <Id = Unit> item(lambda: DlgTextItemDef<Id>.() -> Unit) =
    DlgTextItemDef.build(lambda)

TypeScript can do it, so why can’t Kotlin?

You can specify which name to use on the JVM using @JvmName("something"). The given name is only used when you call your code from other JVM languages like Java.

1 Like