Reputation: 17023
Conceptually I want to do this:
// Expect file (commonMain)
expect class PlatformDir
// Platform-specific implementation for JVM
actual typealias PlatformDir = File
// Platform-specific implementation for Linux/macOS
actual typealias PlatformDir = CPointer<DIR>
The simple JVM type is accepted but the parameterized type of Linux/macOS is not:
Expected class 'PlatformDir' has no actual declaration in module for Native The following declaration is incompatible because number of type parameters is different: public actual typealias PlatformDir = CPointer
Type arguments in the right-hand side of actual type alias should be its type parameters in the same order, e.g. 'actual typealias Foo<A, B> = Bar<A, B>'
Actual typealias 'PlatformDir' has no corresponding expected declaration The following declaration is incompatible because number of type parameters is different: public final expect class PlatformDir
Moving the parameterized type first into its own typealias also doesn't work:
private typealias CPointer_DIR = CPointer<DIR>
actual typealias PlatformDir = CPointer_DIR
It still complains about the wrong number of type parameters and has this additional error:
Right-hand side of actual type alias should be a class, not another type alias
I'm very much a noob in Kotlin and JVM as well as Kotlin Multiplatform so I feel this must be possible without wrapping both in a class. Googling I can't find anybody discussing this and the AI chatbots seem to just clutch at straws that get more and complex and don't build either.
Upvotes: 2
Views: 1313
Reputation:
You are trying to use a simple type for JVM and a parameterized type for Native platforms, but unfortunately, Kotlin doesn't support having different numbers of type parameters in expect and actual declarations.
However, you can achieve your desired outcome with a slightly different approach using a generic class in your expect declaration and then providing the actual implementations. Here's an example:
// Expect file (commonMain)
expect class PlatformDir<T>
// Platform-specific implementation for JVM
actual typealias PlatformDir<T> = File
// Platform-specific implementation for Linux/macOS
actual typealias PlatformDir<T> = CPointer<DIR>
In this case, you're using a generic class in your expect declaration, and then for each platform, you provide the actual implementation. For JVM, the type parameter T is not actually used, while for Native platforms, it's used as expected.
Keep in mind that this approach can be somewhat confusing, as the type parameter T is not really necessary in the JVM implementation. It's more of a workaround to maintain compatibility between different platforms.
Upvotes: 3