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

Add support for polymorphic list validation #59

Open
inakov opened this issue Sep 14, 2022 · 2 comments
Open

Add support for polymorphic list validation #59

inakov opened this issue Sep 14, 2022 · 2 comments
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@inakov
Copy link

inakov commented Sep 14, 2022

Hello, I have one use-case that I cannot achieve with the library right now. I have a list of multiple common types and I want to have specific validation for each type. For example:

sealed interface Event {
    val id: ObjectId
    val start: Instant
    val end: Instant
    ... some other common fileds
}

data class ConcertEvent(
     val band: String,
     ... other fields
): Event

data class TheaterEvent(
     val stage: String,
     ... other fields
): Event

data class Subscribe(
    val events: List<Event>,
    ... other fields
);

Currently, if I want to add validation for Subscribe.events I can do this only by validating Event fields with

Subscribe.events onEach {
     here we cannot have validation for `TheaterEvent` or `ConcertEvent` fields only for `Event`
}

I think is going to be very useful if we have something like this

Subscribe.events onEach<ConcertEvent> {
    ConcertEvent::band required {}
}

Subscribe.events onEach<TheaterEvent> {
    TheaterEvent::stage required {}
   ... other validations
}

What do you think? Is it possible to achieve similar result? Do you think there would be a better approach?

PS. Konform is great! I love it.

@dhoepelman
Copy link
Collaborator

This would be good to have support for. It's probably relatively easy to do, I think some thing(s) are not marked as covariant when they should be.

An existing workaround for this is:

@Supress("UNCHECKED_CAST")
fun <T: Event> eventValidation = Validation<Event> {
  Event::stage required {}
} as Validation<T>

val theaterEventValidation = eventValidation<TheaterEvent>

@dhoepelman dhoepelman added good first issue Good for newcomers enhancement New feature or request labels May 10, 2024
@koenreiniers
Copy link

koenreiniers commented May 30, 2024

Ran into a similar issue today. This is is how I solved it:

class Canvas(val shapes: List<Shape>)
sealed interface Shape
class Circle(val radius: Int): Shape
class Square(val sideLength: Int): Shape

class ShapeValidation : Validation<Shape> {
    private val circleValidation = Validation {
        Circle::radius {
            minimum(0)
        }
    }

    private val squareValidation = Validation {
        Square::sideLength {
            minimum(0)
        }
    }

    override fun validate(value: Shape): ValidationResult<Shape> {
        return when (value) {
            is Circle -> circleValidation(value)
            is Square -> squareValidation(value)
        }
    }
}

val canvasValidation = Validation {
    Canvas::shapes onEach {
        run(ShapeValidation())
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

3 participants