Skip to content

Add an annotation that allows marking properties as required #47

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

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package dev.adamko.kxstsgen

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.InheritableSerialInfo

/**
* Marks a property as required in the generated TypeScript interface.
*
* This annotation is inheritable, so it should be sufficient to place it on a base class of hierarchy.
*
* This annotation should only be used if [kotlinx.serialization.json.JsonConfiguration.encodeDefaults]
* is set to true. If it is false (which it is by default), then properties with default values are
* potentially omitted from the generated JSON.
*/
@InheritableSerialInfo
@Target(AnnotationTarget.PROPERTY)
@ExperimentalSerializationApi
annotation class KxsTsRequired
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.adamko.kxstsgen.core

import dev.adamko.kxstsgen.KxsTsRequired
import kotlinx.serialization.descriptors.PolymorphicKind
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.SerialDescriptor
Expand Down Expand Up @@ -207,7 +208,9 @@ fun interface TsElementConverter {
return descriptor.elementDescriptors.mapIndexed { index, fieldDescriptor ->
val name = descriptor.getElementName(index)
val fieldTypeRef = typeRefConverter(fieldDescriptor)
val optional = descriptor.isElementOptional(index)
val optional =
descriptor.getElementAnnotations(index).none { it is KxsTsRequired }
&& descriptor.isElementOptional(index)
TsProperty(name, fieldTypeRef, optional)
}.toSet()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package dev.adamko.kxstsgen.core

import dev.adamko.kxstsgen.KxsTsConfig
import dev.adamko.kxstsgen.KxsTsGenerator
import dev.adamko.kxstsgen.KxsTsRequired
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import kotlinx.serialization.Serializable

class KxsTsGeneratorTest : FunSpec({
val config = KxsTsConfig(indent = " ")
val tsGenerator = KxsTsGenerator(config)

test("Can make default-valued properties required") {
@Serializable
data class OptionalTest(
val optional: Boolean = false,
@KxsTsRequired
val required: Boolean = true,
)

tsGenerator.generate(OptionalTest.serializer()) shouldBe """
|export interface OptionalTest {
| optional?: boolean;
| required: boolean;
|}
""".trimMargin()
}

test("Can make nullable properties required") {
@Serializable
data class OptionalTest(
@KxsTsRequired
val required: Boolean? = null,
val optional: Boolean? = null,
)

tsGenerator.generate(OptionalTest.serializer()) shouldBe """
|export interface OptionalTest {
| required: boolean | null;
| optional?: boolean | null;
|}
""".trimMargin()
}
})