[prototype] Generate TypeScript interfaces from Kotlin classes

Overview

Kotlinx Serialization TypeScript Generator

Kotlinx Serialization TypeScript Generator creates TypeScript interfaces from Kotlinx Serialization classes.

@Serializable
class MyClass(
  val aString: String,
  var anInt: Int,
  val aDouble: Double,
  val bool: Boolean,
  private val privateMember: String,
)

fun main() {
  val tsGenerator = KxsTsGenerator()
  println(tsGenerator.generate(MyClass.serializer()))
}

Generated TypeScript interface:

export interface MyClass {
  aString: string;
  anInt: number;
  aDouble: number;
  bool: boolean;
  privateMember: string;
}

Only Kotlinx Serialization SerialDescriptors are used to generate TypeScript. They are flexible and comprehensive enough to allow for accurate TypeScript code, without any deviation.

See the docs for working examples.

Status

This is a proof-of-concept.

The aim is to create TypeScript interfaces that can accurately produce Kotlinx Serialization compatible JSON.

Status Notes
Kotlin multiplatform The codebase is multiplatform, but only JVM has been tested
@SerialName / The serial name is directly converted and might produce invalid TypeScript
Basic classes example
Nullable and default-value properties example
Value classes example
Enums example
Lists example
Maps / example Maps with complex keys are converted to an ES6 Map, see documentation
Polymorphism - Sealed classes / example Nested sealed classes are ignored, see documentation
Polymorphism - Open classes example Not implemented. Converted to type MyClass = any
@JsonClassDiscriminator Not implemented
JSON Content polymorphism example Not implemented. Converted to type MyClass = any
Edge cases - circular dependencies example
Comments
  • Add an annotation that allows marking properties as required

    Add an annotation that allows marking properties as required

    This PR provides an annotation that allows marking properties that have default values as required in the TypeScript code.

    The primary use case we have for this is for Read DTOs that have default values that are guaranteed to always be present by the time they reach the TypeScript code.

    This is safe to use as long as encodeDefaults = true is set in the server's Json config. Otherwise all properties with default values should be considered optional.

    opened by nschulzke 4
  • Publish on Maven

    Publish on Maven

    Hello, it would be great to have this package on maven.

    In my case I'm stuck on Maven since am using cloud functions and they require maven pom.xml unless you want to build and upload a jar. All my dependencies including kotlinx.serialization are maven except this packages.

    enhancement 
    opened by abhishiv 4
  • Add an option to use 'brand type' on value classes and primitives

    Add an option to use 'brand type' on value classes and primitives

    To help emulate Kotlin's strong typing, use 'brand typing' to specify primitives and value classes. Otherwise TypeScript doesn't discriminate between UInt and Long

    Builtin primitives should be handled

    type Byte = number & { __kotlin_byte__ : void};
    

    Value classes too

    package my.package
    
    @Serializable
    @JvmInline
    value class UserCount(private val count: UInt)
    

    Something like this...

    type UInt = number & { __kotlin_uint__ : void};
    
    type UserCount = UInt & { __my_package__usercount__ : void};
    
    enhancement 
    opened by aSemy 1
  • add demo for making properties required with `@Required`

    add demo for making properties required with `@Required`

    Adding some docs to demo how @Required can be used to make properties required.

    cc @nschulzke https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/47

    opened by aSemy 0
  • GitHub workflows tests + test & compilation improvements

    GitHub workflows tests + test & compilation improvements

    • Create GitHub workflows for running tests
    • add an option for enabling/disabling the TS compile tests
    • fix TS compile assertions
    • misc version bumps
    • disable Kotest JS tests (blocked by https://github.com/kotest/kotest/issues/3141)
    • bump to jvm11, kotlin-level 1.7
    • enable test-fixtures in knit tests, and re-organise source sets
    opened by aSemy 0
  • Continuous development

    Continuous development

    • version bump Kotlin 1.6.20
    • jdk decrease to 1.8 (wider compatibility)
    • set up version catalogue and platform
    • Knit test improvements
    • fix sealed class enums
    • map types: allow overriding, and consider existing overrides
    • fix tuple deserialization
    • indexed types: allow for number keys
    • disable unused 'descriptor extractor' reflection code
    • enable Kotlin/JS
    opened by aSemy 0
  • Maps with 'value class' keys that have primitive values should be converted to indexed types

    Maps with 'value class' keys that have primitive values should be converted to indexed types

    PrototypeKey is a primitive, so it's a valid value for an indexed type key.

    export interface Dictionary {
      protos: Map<PrototypeKey, PrototypeName>; // actual
      protos: { [key: PrototypeKey]: { [key: string]: PrototypeKey } }; // expected
    }
    
    export type PrototypeKey = string;
    
    bug enhancement 
    opened by aSemy 0
  • Generate labelled tuple elements

    Generate labelled tuple elements

    https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html#labeled-tuple-elements

    Should be very easy to do, and the TS is much more clear.

    enhancement 
    opened by aSemy 0
  • #24 TS Compilation testing

    #24 TS Compilation testing

    fixes #24

    Also fixes an issue where nullable keys in maps should be converted to Map<>, not an indexed type. Update docs and tests for this case.

    opened by aSemy 0
  • Knit tests: check if the produced code is valid TypeScript

    Knit tests: check if the produced code is valid TypeScript

    Currently the Knit tests only do a string comparison. But that doesn't mean the expected string is correct TypeScript...

    1. add the Gradle Node plugin, download TypeScript
    2. download TypeScript npx task
    3. in the tests, try compiling the generated TypeScript using a command line arg npx tsc (somehow? I'm not sure about this...)
    4. Check there's no errors (again, I'm not sure)
    enhancement 
    opened by aSemy 0
  • Continuous improvements: Tuples, TypeUnions, descriptor extraction

    Continuous improvements: Tuples, TypeUnions, descriptor extraction

    • make the Tuples API a little nicer by returning an iterator to the constructor, so there's no need for fetching elements by index.
    • extract descriptors from sealed subclasses properties (they were previously ignored)
    • create a specific 'TypeUnion' declaration, so the type aliases are more distinct and the brand typing only works on type aliases
    opened by aSemy 0
  • Provide an easier way to set default TypeScript elements, so generated code can be customised more easily

    Provide an easier way to set default TypeScript elements, so generated code can be customised more easily

    If a client already has some standard type aliases, then I want to re-use those type aliases in my generated code.

    @Serializable
    data class Position(
      val x: Double,
      val y: Double,
    )
    
    // provided by library
    export type double = number
    
    // I want generated code to use 'double'
    export interface Position {
      x: double;
      y: double;
    }
    

    If I hack around a bit, I can come up with something that works. But it's not pretty, or intuitive

    fun main() {
      val tsGenerator = KxsTsGenerator()
    
      val libraryDoubleTypeRef = TsTypeRef.Declaration(TsElementId("Double"), null, false)
    
      tsGenerator.descriptorElements += Double.serializer().descriptor to setOf(
        TsDeclaration.TsTypeAlias(
          TsElementId("Double"),
          TsTypeRef.Declaration(TsElementId("double"), null, false),
        )
      )
    
      tsGenerator.descriptorTypeRef += mapOf(
        Double.serializer().descriptor to libraryDoubleTypeRef
      )
    
      println(tsGenerator.generate(Position.serializer()))
    }
    
    @Serializable
    data class Position(
      val x: Double,
      val y: Double,
    )
    

    This produces the correct output...

    export interface Position {
      x: Double;
      y: Double;
    }
    
    export type Double = double;
    

    Good luck figuring that out if you're new to KXS, and didn't happen to build this library...

    Potential solutions

    Users should be able to set overrides for SerialDescriptors, similar to the existing serializerDescriptors and descriptorElements in KxsTsGenerator. For example

    val gen = KxsTsGenerator()
    
    gen.addOverride(
      Double.serializer().descriptor to existingTypeAlias("double"),
    )
    
    enhancement 
    opened by aSemy 0
  • Export numeric types (Double, Float) as named type aliases, so generated TypeScript closely resembles Kotlin

    Export numeric types (Double, Float) as named type aliases, so generated TypeScript closely resembles Kotlin

    Double and Int are both converted directly to number. This is confusing on the TypeScript side.

    @Serializable
    data class Position(
      val x: Double,
      val y: Double,
      val level: Int,
    )
    
    // generated
    export interface Position {
      x: number;
      y: number;
      level: number; // level looks the same as x and y, but if I produce a JSON message with 1.5, KXS will error
    }
    

    Unsigned numbers (because they are value classes) are converted to type aliases, e.g.

    export interface Score {
      goals: UInt;
    }
    
    export type UInt = number;
    

    In TypeScript this isn't safe (UInt can accept any numeric value, despite its name) - but it gives a good indication, and can be enhanced with brand typing (#7).

    Can the other numeric primitives be exported as type aliases?

    export type Byte = number
    export type Short = number
    export type Int = number
    export type Long = number
    export type Float = number
    export type Double = number
    
    enhancement 
    opened by aSemy 0
  • Change Knit tests be multiplatform Kotlin, so they test all platforms

    Change Knit tests be multiplatform Kotlin, so they test all platforms

    Ideally the test should work on all platforms, but getting the tests working on JVM and JS would be a good first step

    Requires some way of capturing log output on all platforms (e.g. https://github.com/kotest/kotest/issues/2914)

    help wanted 
    opened by aSemy 0
  • Handle generic properties and classes

    Handle generic properties and classes

    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>
    )
    
    1. Generic classes
    class WrapperClass<T>(
      val type: T
    )
    
    1. Generic constraints
    interface MyInterface
    class WrapperClass<T: MyInterface>(
      val type: T
    )
    
    1. Inheritance plus generics
    interface MyInterface<T>
    class WrapperClass<T>(
      val type: T
    ) : MyInterface<T>
    
    1. Wildcards
    class SomeClass(
      val type: List<*>
    )  
    
    enhancement help wanted 
    opened by aSemy 1
  • Create a Gradle plugin, so TypeScript files are generated during compilation

    Create a Gradle plugin, so TypeScript files are generated during compilation

    The plugin will scan for all classes with @Serializable. It will convert each to a TypeScript definition.

    Nice extras

    1. kxs-ts-gen is configurable

    2. Add a @TsExport annotation so only specific types are generated

    3. Allow @TsExport to be added to const strings, and the raw value will be exported (inspired by https://github.com/ntrrgc/ts-generator/issues/24)

      @TsExport
      const val customConfig: String = """
      object ApiConstants {
          const SOME_VAL_1 = 1234
          const SOME_VAL_2 = "hello world"
      }
      """
      

      kxs-ts-gen will produce

      object ApiConstants {
          const SOME_VAL_1 = 1234
          const SOME_VAL_2 = "hello world"
      }
      

      Or maybe directly convert a const

      object ApiConstants {
        @TsExport
        const val SOME_VAL_1 = 1234
        @TsExport
        const val SOME_VAL_2 = "hello world"
      }
      

      kxs-ts-gen will produce

      object ApiConstants {
          const SOME_VAL_1 = 1234
          const SOME_VAL_2 = "hello world"
      }
      
    4. Grab KDoc, and convert it to JSDoc

    5. Grab annotations and convert them https://github.com/ntrrgc/ts-generator/issues/23

    ~~Use KSP to create a plugin.~~ KSP is unsuitable, it can only view and can't run code, use https://github.com/ronmamo/reflections or https://github.com/classgraph/classgraph instead?

    enhancement 
    opened by aSemy 0
Releases(v0.2.1)
  • v0.2.1(Jul 2, 2022)

    What's Changed

    • Development by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/46

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/compare/v0.2.0...v0.2.1

    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Jun 12, 2022)

    What's Changed

    • Fixing Maven Central publishing in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/43 and https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/45
    • Kotlin 1.7 & other version bumps by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/44

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/compare/v0.1.4...v0.2.0

    Source code(tar.gz)
    Source code(zip)
  • v0.1.4(Jun 4, 2022)

    What's Changed

    • bump jitpack jdk by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/41
    • Fix maven central publishing by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/42

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/compare/v0.1.3...v0.1.4

    Source code(tar.gz)
    Source code(zip)
  • v0.1.3(Jun 3, 2022)

    What's Changed

    • Maven publishing by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/40

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/compare/v0.1.2...v0.1.3

    Source code(tar.gz)
    Source code(zip)
  • v0.1.2(Jun 3, 2022)

    What's Changed

    • Maven publishing fixes by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/39

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/compare/v0.1.1...v0.1.2

    Source code(tar.gz)
    Source code(zip)
  • v0.1.1(Jun 2, 2022)

    What's Changed

    • Build and release fixes by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/37

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/compare/v0.1.0...v0.1.1

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Jun 2, 2022)

    What's Changed

    • Continuous improvements: Tuples, TypeUnions, descriptor extraction by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/21
    • #24 TS Compilation testing by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/25
    • #26 named tuples by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/27
    • Handle maps with type-alias keys by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/29
    • Element overriding by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/30
    • allow for custom literals, for better overriding #23 by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/31
    • Continuous development by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/32
    • Version bumps by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/34
    • Publish to Maven Central by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/35

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/compare/v0.0.5...v0.1.0

    Source code(tar.gz)
    Source code(zip)
  • v0.0.5(Apr 8, 2022)

    What's Changed

    • Refine implementation by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/17

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/compare/v0.0.4...v0.0.5

    Source code(tar.gz)
    Source code(zip)
  • v0.0.4(Apr 4, 2022)

    What's Changed

    • Update package structure by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/16

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/compare/v0.0.3...v0.0.4

    Source code(tar.gz)
    Source code(zip)
  • v0.0.3(Apr 4, 2022)

    What's Changed

    • Refine implementation by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/14

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/compare/v0.0.2...v0.0.3

    Source code(tar.gz)
    Source code(zip)
  • v0.0.2(Apr 3, 2022)

    What's Changed

    • Initial implementations for code generation by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/13

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/commits/v0.0.2

    Source code(tar.gz)
    Source code(zip)
  • v0.0.1(Apr 3, 2022)

    What's Changed

    • Initial implementations for code generation by @aSemy in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/8

    New Contributors

    • @aSemy made their first contribution in https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/pull/8

    Full Changelog: https://github.com/adamko-dev/kotlinx-serialization-typescript-generator/commits/v0.0.1

    Source code(tar.gz)
    Source code(zip)
Owner
null
This library is a set of simple wrapper classes that are aimed to help you easily access android device information.

SysInfo Simple, single class wrapper to get device information from an android device. This library provides an easy way to access all the device info

Klejvi Kapaj 7 Dec 27, 2022
Clean MVVM with eliminating the usage of context from view models by introducing hilt for DI and sealed classes for displaying Errors in views using shared flows (one time event), and Stateflow for data

Clean ViewModel with Sealed Classes Following are the purposes of this repo Showing how you can remove the need of context in ViewModels. I. By using

Kashif Mehmood 22 Oct 26, 2022
Auto-generate the fastest possible Parcelable implementations for Java and Kotlin

This project is deprecated It will still be maintained, but no new features will be added. Please use Parcelize, as it is the official way of generati

Bradley Campbell 492 Nov 17, 2022
This is a Kotlin multiplatform template project used to generate and deploy a natively compiled AWS lambda function using the custom runtime.

Overview This is a Kotlin multiplatform template project used to generate and deploy a natively compiled AWS Lambda function using a custom runtime. U

Greg Steckman 5 Jun 25, 2022
A Gradle plugin for Kotlin Multiplatform projects that generate a XCFramework for Apple targets or a FatFramework for iOS targets, and manages the publishing process in a CocoaPod Repository.

KMP Framework Bundler KMP Framework Bundler is a Gradle plugin for Kotlin Multiplatform projects that generate a XCFramework for Apple targets or a Fa

Marco Gomiero 17 Oct 29, 2022
💫 A Gradle Plugin to generate your networking code from Swagger

Swagger Gradle Codegen A Gradle plugin to generate networking code from a Swagger spec file. This plugin wraps swagger-codegen, and exposes a configur

Yelp.com 399 Nov 28, 2022
This program will read from your android application string.xml file and generate translated strings.xml files in your preferred languages using google sheet.

Localize your application content This program will read from your application string.xml file and generate translated strings.xml files in your prefe

DhiWise 4 Jul 29, 2022
Koin Annotations - help declare Koin definition in a very fast and intuitive way, and generate all underlying Koin DSL for you

The goal of Koin Annotations project is to help declare Koin definition in a very fast and intuitive way, and generate all underlying Koin DSL for you. The goal is to help developer experience to scale and go fast ?? , thanks to Kotlin Compilers.

insert-koin.io 68 Jan 6, 2023
Run Kotlin/JS libraries in Kotlin/JVM and Kotlin/Native programs

Zipline This library streamlines using Kotlin/JS libraries from Kotlin/JVM and Kotlin/Native programs. It makes it possible to do continuous deploymen

Cash App 1.5k Dec 30, 2022
A somewhat copy past of Jetbrain's code from the kotlin plugin repo to make it humanly possible to test Intellij IDEA kotlin plugins that work on kotlin

A somewhat copy past of Jetbrain's code from the kotlin plugin repo to make it humanly possible to test Intellij IDEA kotlin plugins that work on kotlin

common sense OSS 0 Jan 20, 2022
Real life Kotlin Multiplatform project with an iOS application developed in Swift with SwiftUI, an Android application developed in Kotlin with Jetpack Compose and a backed in Kotlin hosted on AppEngine.

Conferences4Hall Real life Kotlin Multiplatform project with an iOS application developed in Swift with SwiftUI, an Android application developed in K

Gérard Paligot 98 Dec 15, 2022
Android + Kotlin + Github Actions + ktlint + Detekt + Gradle Kotlin DSL + buildSrc = ❤️

kotlin-android-template ?? A simple Github template that lets you create an Android/Kotlin project and be up and running in a few seconds. This templa

Nicola Corti 1.5k Jan 3, 2023
LifecycleMvp 1.2 0.0 Kotlin is MVP architecture implementation with Android Architecture Components and Kotlin language features

MinSDK 14+ Download Gradle Add to project level build.gradle allprojects { repositories { ... maven { url 'https://jitpack.io' }

Robert 20 Nov 9, 2021
Opinionated Redux-like implementation backed by Kotlin Coroutines and Kotlin Multiplatform Mobile

CoRed CoRed is Redux-like implementation that maintains the benefits of Redux's core idea without the boilerplate. No more action types, action creato

Kittinun Vantasin 28 Dec 10, 2022
👋 A common toolkit (utils) ⚒️ built to help you further reduce Kotlin boilerplate code and improve development efficiency. Do you think 'kotlin-stdlib' or 'android-ktx' is not sweet enough? You need this! 🍭

Toolkit [ ?? Work in progress ⛏ ?? ??️ ?? ] Snapshot version: repositories { maven("https://s01.oss.sonatype.org/content/repositories/snapshots") }

凛 35 Jul 23, 2022
An app architecture for Kotlin/Native on Android/iOS. Use Kotlin Multiplatform Mobile.

An app architecture for Kotlin/Native on Android/iOS. Use Kotlin Multiplatform Mobile. 项目架构主要分为原生系统层、Android/iOS业务SDK层、KMM SDK层、KMM业务逻辑SDK层、iOS sdkfra

libill 4 Nov 20, 2022
Provides Kotlin libs and some features for building Kotlin plugins

Kotlin Plugin Provides Kotlin libs and some features for building awesome Kotlin plugins. Can be used instead of CreeperFace's KotlinLib (don't use to

null 3 Dec 24, 2021
Notes-App-Kotlin - Notes App Built Using Kotlin

Notes-App-Kotlin Splash Screen Home Page Adding New Notes Filter Feature Search

Priyanka 4 Oct 2, 2022
Kotlin-client-dsl - A kotlin-based dsl project for a (Client) -> (Plugin) styled program

kotlin-client-dsl a kotlin-based dsl project for a (Client) -> (Plugin) styled p

jackson 3 Dec 10, 2022