hippietrail
hippietrail

Reputation: 17023

In Kotlin Multiplatform can I have an 'expect' type that is a simple type on one platform and a parameterized type on another?

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

Answers (1)

user11853725
user11853725

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

Related Questions