Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export enum as String/Int #5

Open
glureau opened this issue Nov 13, 2021 · 1 comment
Open

Export enum as String/Int #5

glureau opened this issue Nov 13, 2021 · 1 comment
Assignees
Labels

Comments

@glureau
Copy link
Collaborator

glureau commented Nov 13, 2021

Exporting enum to a class to be able to map additional properties and functions is increasing the JS bundle size. An alternative could be to export an enum as a string for example:

@KustomExport(exportMode = ExportMode.Enum.asString)
enum class Direction {
    NORTH, SOUTH, WEST, EAST
}

We could have a default mode to auto that could choose the mode asString or asInt if there is only one String/Int parameter, and choose the full wrapper when there is more than 1 constructor param or a method.

Full fledge wrapper
import sample._enum.Direction as CommonDirection // The annotated enum in commonMain

@JsExport
public class Direction internal constructor(
    internal val `value`: CommonDirection
) {
    public val name: String = value.name
}

public fun Direction.importDirection(): CommonDirection = value

public fun CommonDirection.exportDirection(): Direction = Direction(this)

@JsExport
public object Directions {
    public val NORTH: Direction = CommonDirection.NORTH.exportDirection()

    public val SOUTH: Direction = CommonDirection.SOUTH.exportDirection()

    public val WEST: Direction = CommonDirection.WEST.exportDirection()

    public val EAST: Direction = CommonDirection.EAST.exportDirection()
}
Export as String
import sample._enum.Direction as CommonDirection // The annotated enum in commonMain

typealias Direction = String

public fun Direction.importDirection(): CommonDirection = CommonDirection.valueOf(this)

public fun CommonDirection.exportDirection(): Direction = this.name

@JsExport
public const val Directions_NORTH: Direction = "NORTH"
@JsExport
public const val Directions_SOUTH: Direction = "SOUTH"
@JsExport
public const val Directions_WEST: Direction = "WEST"
@JsExport
public const val Directions_EAST: Direction = "EAST"

Bundle size (js) : 428 chars saved (no compressed) when exporting as strings (vs the full fledged export). A big part of the gain come from removing the object Directions and using (const) val instead, if we keep an object Dimensions the gain is only 14 chars. (So it's probably better to remove the object for the full fledged export, also const as no impact on bundle size.)

Limitations:

  • only available when there is no methods/properties (we may be able to use the 1st param instead of name when only one param is defined)
  • fun goTo(d: Direction) will be exported as goTo(direction: string); (as expected). It allows passing any string value, but a bad string will generate an IllegalStateException, possibly crashing the app.

Eventually there is an issue today with KSP/KotlinJsIr on multi-modules where external dependencies are not resolvable (WIP). With the current implementation, we expect a class not resolvable to be from another module, and it could be an issue with typealias resolution (not tested yet).

Also a little note about enums, Kotlin 1.6.20 should export enums without an additional layer... https://youtrack.jetbrains.com/issue/KT-37916

@glureau glureau self-assigned this Nov 13, 2021
@glureau
Copy link
Collaborator Author

glureau commented Jan 26, 2022

Didn't have a lot of time to work on this topic, and 1.6.20 should come soon with a better enum support, so this topic is in standby for now.

@glureau glureau added the standby label Feb 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant