Dagger で @JvmInline value class は inject できません

github.com

DDD の本を読んだりして、いろいろ class 化して表すのだ、という意識が出てきたり出てこなかったりして、Id となる文字列や数値を class 化しようと誰もが思うはず(要出典)。

その時に、良かれと思って value class を検討していくだろう。

@JvmInline value class MyId(val value: Long)

2025/02/01 現在は Dagger / Hilt でこれを inject しようとしてもできない。

例えば ViewModel に inject して、この MyId を UseCase や Repository に渡すのだ、と思ってもコンパイルエラーになります。

@HiltViewModel(assistedFactory = MyViewModel.Factory::class)
class MyViewModel @AssistedInject constructor(
    @Assisted private val myId: MyId,
    private val repository: Repository,
) : ViewModel() {
    @AssistedFactory
    interface Factory {
        fun create(myId: MyId): MyViewModel
    }

    init {
        repository.getData(myId)
    }
...
[ksp] java.lang.IllegalArgumentException: not a valid name: create-OUFw_og
    at com.squareup.javapoet.Util.checkArgument(Util.java:53)
    at com.squareup.javapoet.MethodSpec$Builder.setName(MethodSpec.java:315)
    at com.squareup.javapoet.MethodSpec$Builder.<init>(MethodSpec.java:310)
    at com.squareup.javapoet.MethodSpec$Builder.<init>(MethodSpec.java:294)
    at com.squareup.javapoet.MethodSpec.methodBuilder(MethodSpec.java:188)

じゃあ ViewModel に渡すときはどうするかというと、value class の中身を取り出して inject するか、value class をラップした class を作成するしかない。 例えば value class の中身を取り出してやるとこんな感じか。

@HiltViewModel(assistedFactory = MyViewModel.Factory::class)
class MyViewModel @AssistedInject constructor(
    @Assisted myId: Long,
    private val repository: Repository,
) : ViewModel() {
    @AssistedFactory
    interface Factory {
        fun create(myId: Long): MyViewModel
    }

    private val myId: MyId = MyId(myId)

    init {
        repository.getData(myId)
    }
...

悲しい感じがする。