https://kotlinlang.org logo
#getting-started
Title
# getting-started
a

Ayfri

02/14/2022, 10:21 PM
Hi, I fell into a little types mangling while doing a library for Kotlin/JS, I typed some events types that uses
eventemitter3
library with a pretty ugly (I think) but simple solution
Copy code
sealed interface DisplayObjectEvents<T : Any> {
	object added : DisplayObjectEvents<Container>
	object click : DisplayObjectEvents<FederatedPointerEvent>
	object clickcapture : DisplayObjectEvents<FederatedPointerEvent>
	object destroyed : DisplayObjectEvents<Nothing>
	object mousedown : DisplayObjectEvents<FederatedPointerEvent>
    ...
	(there are almost 100 elements in total)
}
But I want to be able to use it like that
myObject.on<DisplayObjectEvents.added> { // it is Container here }
, so I created this
Copy code
inline fun <reified T : DisplayObjectEvents<T>> DisplayObject.on(noinline callback: (T) -> Unit) = on(T::class.simpleName!!, callback as ListenerFn, null)
// ListenerFn is just a function type that take Any arguments Any number of time
// Which is the default type for my library for events in TypeScript
But
Copy code
myObject.on<DisplayObject.added> {
    // it is of type DisplayObject.added
}
What I've done wrong ?
I've come up with a solution that requires an argument instead of reified type but if I can avoid it it would be nice
Copy code
inline fun <T : Any> DisplayObject.on(event: DisplayObjectEvents<T>, noinline callback: (T) -> Unit) = on(event::class.simpleName!!, callback as ListenerFn, null)

myObject.on(DisplayObjectEvents.added) {
	// it is correctly of type Container
}
r

Ruckus

02/14/2022, 10:33 PM
reified T : DisplayObjectEvents<T>
means that
T
needs to be both a
DisplayObjectEvents
as well as its generic parameter. You could either pass in a parameter (as you've done) or have two generic types.
You should see some sort of bounds warning if you try
on<DisplayObjectEvents.added>
, since
added
has a generic of
Container
which does not fit the restriction
T : DisplayObjectEvents<T>
.
With two generics it would be something like
Copy code
inline fun <reified D : DisplayObjectEvents<T>, T : Any> DisplayObject.on(noinline callback: (T) -> Unit) = on(D::class.simpleName!!, callback as ListenerFn, null)
And used like
Copy code
obj.on<DisplayObjectEvents.added, Container> { ... }
But I personally think the extra parameter version you have is cleaner.
a

Ayfri

02/14/2022, 10:45 PM
Yes I've seen these problem, and if I put two generic types it's asking me to declare both when using the method so I loose the utility of what I'm trying to do I guess I'll stick with using a parameter
👍 2
4 Views