Kotlin typealias

The typealias can be handy to define very simple types. But be aware that it is not represented in bytecode. The typealiases are simply replaced by the type they represent and so can't be used for function signatures. See also Type aliases

Issues

By using typealiases code can become fuzzy very quickly. Especially when using typealiasses in typealiasses.

Bean injection is first done based on name but if that fails it is done based on type. But when using typealiasses the type is not clear when looking at the code. Unexpected results might arrise when the named bean is renamed and there is only one alternative based on type. Then that other bean is silently injected.

Examples

See some examples below

import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean

typealias TypeOne = String
typealias TypeTwo = String

typealias SignatureOne = () -> String
typealias SignatureTwo = () -> String

@SpringBootTest
class ExperimentMilo {
@TestConfiguration
class TestConfig {
@Bean
fun funOne(): SignatureOne = { "FunOne" }

@Bean
fun funTwo(): SignatureTwo = { "FunTwo" }
}

// Those are resolved based on the name of the bean. The variable name is exactly
// the same as the bean name
@Autowired lateinit var funOne: SignatureOne
@Autowired lateinit var funTwo: SignatureTwo

// Those can't be resolved based on the name and so are resolved based on the type.
// This would give an error because there are multiple beans with the same type.
// By using 'Qualifiers' we force the specific bean.
@Autowired @Qualifier("funOne") lateinit var functionOne: SignatureOne
@Autowired @Qualifier("funTwo") lateinit var functionTwo: SignatureTwo

@Test
fun testBeanSignature() {
val resultOne = funOne.invoke()
val resultTwo = funTwo.invoke()

Assertions.assertEquals("FunOne", resultOne)
Assertions.assertEquals("FunTwo", resultTwo)
}

@Test
fun testBeanSignature2() {
val resultOne = functionOne.invoke()
val resultTwo = functionTwo.invoke()

Assertions.assertEquals("FunOne", resultOne)
Assertions.assertEquals("FunTwo", resultTwo)
}

@Test
fun testFunctionSignature() {
val one: TypeOne = "One"
val two: TypeTwo = "Two"

val resultOneTwo = testSignature(one, two)
val resultTwoOne = testSignature(two, one)

Assertions.assertEquals(Pair("One", "Two"), resultOneTwo)
Assertions.assertEquals(Pair("Two", "One"), resultTwoOne)
}

fun testSignature(one: TypeOne, two: TypeTwo): Pair<TypeOne, TypeTwo> {
return Pair(one, two)
}
}