· seedling · kmp, ios
Swift loses the type of a Kotlin Flow, because Flow is an interface
Kotlin/Native talks to Swift through an Objective-C header, and Objective-C only puts generics on classes. Flow is an interface, so its element type doesn't survive the trip.
The gap
I learned that Swift sees the values of a Kotlin Flow<User> as Any?, and accepted it as a fact. What I was missing was the reason, so I couldn't predict which other types would lose information too.
The pieces
- Kotlin/Native doesn't produce Swift. It produces a framework with an Objective-C header, and Swift reads that header.
- Objective-C has only "lightweight generics", and they can be defined on classes, not on interfaces (protocols) or functions.
- A Kotlin interface becomes an Objective-C protocol.
Flow<out T>is an interface in kotlinx.coroutines, so it becomes a protocol, and theThas nowhere to go.
The click
The Objective-C header is a restaurant menu that Swift orders from. The menu can print "soup of the day: tomato" next to a dish (a class), but for a protocol it can only print "soup". So a generic class such as Box<User> keeps its type in Swift, while a Flow<User> arrives as "a flow of something", and Swift has to cast.
The same rule predicts the rest: anything generic that isn't a class, such as a generic function, loses its type parameter in the header too.
How I checked it
I read the Kotlin documentation on Objective-C interop: "Generics can only be defined on classes, not on interfaces (protocols in Objective-C and Swift) or functions." The kotlinx.coroutines API reference declares Flow as interface Flow<out T>.
I didn't build an iOS framework to look at the generated header; that needs a Mac. So this card is a seedling until I do.
Check yourself
Does Kotlin/Native translate Kotlin into Swift?
No. It produces a framework with an Objective-C header, and Swift imports that header.
Why does a generic class keep its type parameter in Swift but a Flow doesn't?
Objective-C generics exist only on classes; Flow is an interface, which becomes a protocol, and protocols can't carry generics.
A Kotlin generic function fun <T> first(list: List<T>): T is called from Swift. Will Swift know T?
No. Objective-C generics can't be defined on functions either, so the type parameter is lost.