In Kotlin, there’s no way to check the generic parameters at runtime in general case (like just checking the items of a List<T>, which is only a special case), so casting a generic type to another with different generic parameters will raise a warning unless the cast lies within variance bounds.
There are different solutions, however:
-
You have checked the type and you are quite sure that the cast is safe. Given that, you can suppress the warning with
@Suppress("UNCHECKED_CAST").@Suppress("UNCHECKED_CAST") val waypointList = list as? List<Waypoint> ?: return null -
Use
.filterIsInstance<T>()function, which checks the item types and returns a list with the items of the passed type:val waypointList: List<Waypoint> = list.filterIsInstance<Waypoint>() if (waypointList.size != list.size) return nullor the same in one statement:
val waypointList = list.filterIsInstance<Waypoint>() .apply { if (size != list.size) return null }This will create a new list of the desired type (thus avoiding unchecked cast inside), introducing a little overhead, but in the same time it saves you from iterating through the
listand checking the types (inlist.foreach { ... }line), so it won’t be noticeable. -
Write a utility function that checks the type and returns the same list if the type is correct, thus encapsulating the cast (still unchecked from the compiler’s point of view) inside it:
@Suppress("UNCHECKED_CAST") inline fun <reified T : Any> List<*>.checkItemsAre() = if (all { it is T }) this as List<T> else nullWith the usage:
val waypointList = list.checkItemsAre<Waypoint>() ?: return null