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

Handle generic properties and classes #11

Open
aSemy opened this issue Mar 4, 2022 · 6 comments
Open

Handle generic properties and classes #11

aSemy opened this issue Mar 4, 2022 · 6 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@aSemy
Copy link
Contributor

aSemy commented Mar 4, 2022

This has a large scope. SerialDescriptors are not at all generic. It is probably impossible to get this information from KSX.

  1. Generic fields
    class WrapperClass(
      val type: List<String>
    )
  2. Generic classes
    class WrapperClass<T>(
      val type: T
    )
  3. Generic constraints
    interface MyInterface
    class WrapperClass<T: MyInterface>(
      val type: T
    )
  4. Inheritance plus generics
    interface MyInterface<T>
    class WrapperClass<T>(
      val type: T
    ) : MyInterface<T>
  5. Wildcards
    class SomeClass(
      val type: List<*>
    )  
aSemy added a commit that referenced this issue Apr 4, 2022
- fix element ID name extraction (handle other SerialDescriptors that have < > in them)
- fix knit tests not running
- fix generic test #11
aSemy added a commit that referenced this issue Apr 4, 2022
- workaround for json content polymorphic + test
- fix element ID name extraction (handle other SerialDescriptors that have < > in them)
- fix knit tests not running
- fix generic test #11
@aSemy
Copy link
Contributor Author

aSemy commented Apr 9, 2022

I suspect this will be far too difficult to implement in a nice way. SerialDescriptors don't have any clear 'generic type' information, or if they do then it's very difficult to determine what TypeScript should be produced.

It might be possible with reflection, and clever use of a SerializersModule?

For now, generics are implemented as 'best effort', but I think they should safely fall back to any.

TODO document generics limitations #19

@aSemy aSemy added enhancement New feature or request help wanted Extra attention is needed labels Apr 9, 2022
@natanfudge
Copy link

natanfudge commented Oct 11, 2023

Generic types are very important, and this limitation of Kotlinx.serialization makes me think it should be thrown out of the window and replaced with a KSP processor.
@aSemy are you still using this?

@aSemy
Copy link
Contributor Author

aSemy commented Oct 11, 2023

Hi @natanfudge, thanks for the comment.

Would you be able to provide a specific use case where you need generics? What Kotlin class do you need to use? What Typescript code do you want to be generated? What does kxs-ts-gen currently generate? Are there any workarounds? It would help inform any decisions.

I've always found that it's best to avoid using open-polymorphism with Kotlinx Serialization completely, and that refactoring to use closed-polymorphism will be more work, but it is much more robust and leads to better Typescript.

This library does get used, I can see ~500 downloads last month for the JVM artifact, so it's very much alive and I'm open to evolving it, although I have less time as of late.

@natanfudge
Copy link

data class SearchResult<T> {
    val items: List<T>
    val page: Int
}

Generates

interface SearchResult<T> {
    items: T[]
    page: number
}

Used like

fun getDogs(query: String) : SearchResult<Dogs>

As an API endpoint for example

@aSemy
Copy link
Contributor Author

aSemy commented Oct 12, 2023

Thanks! Just to be clear, can you specify what you want kxs-ts-gen to generate vs what it actually generates?

@natanfudge
Copy link

natanfudge commented Oct 12, 2023

Considering kotlinx.serialization doesn't have a concept of an "undefined type argument", there's no valid argument that would do what I described.
The best kxs-ts-gen can do is

interface SearchResult {
    items: string[]
    page: number
}

Which doesn't involve generic types.

I've investigated kxs-ts-gen for use in my own code generation project, but seeing this limitation I generated the type information myself using a KSP processor.
Given the following data classes:

@Serializable
data class PlayerId(val num: Long)

@Serializable
data class GenericThing<T1, T2, T3>(val x: T1, val y: T2, val z: T3, val w: List<T3> = listOf())

This is how it looks like as raw json type info:

    "models": [
        {
            "name": "PlayerId",
            "properties": {
                "num": {
                    "name": "Long"
                }
            }
        },
        {
            "name": "GenericThing",
            "typeParameters": [
                "T1",
                "T2",
                "T3"
            ],
            "properties": {
                "x": {
                    "name": "T1",
                    "isTypeParameter": true
                },
                "y": {
                    "name": "T2",
                    "isTypeParameter": true
                },
                "z": {
                    "name": "T3",
                    "isTypeParameter": true
                },
                "w": {
                    "name": "List",
                    "typeArguments": [
                        {
                            "name": "T3",
                            "isTypeParameter": true
                        }
                    ]
                }
            }
        },
    ]

Which is modeled after:

@Serializable
data class RpcModel(val name: String, val typeParameters: List<String> = listOf(), val properties: Map<String, RpcType>)

@Serializable
data class RpcType(val name: String, val isTypeParameter: Boolean = false, val typeArguments: List<RpcType> = listOf())

And the Typescript output I've yet to generate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants