Skip to content

Getting Started

This guide will help you add typed-value to your project and start using type-safe values.

Installation

Using the BOM (recommended)

The BOM (Bill of Materials) lets you declare a single versioned dependency and omit versions on individual modules:

kotlin
dependencies {
    implementation(platform("com.ekino.oss:typed-value-bom:1.3.0"))
    implementation("com.ekino.oss:typed-value-core")
    // Add any integration modules without versions
    implementation("com.ekino.oss:typed-value-jackson")
    implementation("com.ekino.oss:typed-value-spring")
}
groovy
dependencies {
    implementation platform('com.ekino.oss:typed-value-bom:1.3.0')
    implementation 'com.ekino.oss:typed-value-core'
    implementation 'com.ekino.oss:typed-value-jackson'
}
xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.ekino.oss</groupId>
            <artifactId>typed-value-bom</artifactId>
            <version>1.3.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.ekino.oss</groupId>
        <artifactId>typed-value-core</artifactId>
    </dependency>
</dependencies>

Without the BOM

kotlin
dependencies {
    implementation("com.ekino.oss:typed-value-core:1.3.0")
    implementation("com.ekino.oss:typed-value-jackson:1.3.0")
    implementation("com.ekino.oss:typed-value-spring:1.3.0")
}
kotlin
kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation("com.ekino.oss:typed-value-core:1.3.0")
            }
        }
    }
}
groovy
dependencies {
    implementation 'com.ekino.oss:typed-value-core:1.3.0'
    implementation 'com.ekino.oss:typed-value-jackson:1.3.0'
    implementation 'com.ekino.oss:typed-value-spring:1.3.0'
}
xml
<dependencies>
    <dependency>
        <groupId>com.ekino.oss</groupId>
        <artifactId>typed-value-core</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>com.ekino.oss</groupId>
        <artifactId>typed-value-jackson</artifactId>
        <version>1.3.0</version>
    </dependency>
    <dependency>
        <groupId>com.ekino.oss</groupId>
        <artifactId>typed-value-spring</artifactId>
        <version>1.3.0</version>
    </dependency>
</dependencies>

Basic Usage

1. Define Your Types

First, define the marker classes that will tag your values:

kotlin
// For identifiers
class User
class Product
class Order

// For quantities
class Banana
class Apple

// For money
class Cents
class Euros

TIP

These can be empty marker classes, data classes, or full entity implementations. The type parameter is only used at compile time for type checking.

2. Create Typed Values

Use extension functions to create typed values from raw primitives:

kotlin
import com.ekino.oss.typedvalue.*

// Type-safe identifiers
val userId = "user-123".toTypedString<User>()
val productId = 42L.toTypedLong<Product>()
val orderId = UUID.randomUUID().toTypedUuid<Order>() // JVM only

// Type-safe quantities
val bananas = 5.toTypedInt<Banana>()
val apples = 3.toTypedInt<Apple>()

// Type-safe money
val priceInCents = 1999L.toTypedLong<Cents>()

3. Use in Domain Models

Define your data classes with typed values:

kotlin
data class UserDto(
    val id: TypedString<User>,
    val name: String,
    val email: String
)

data class CartItem(
    val productId: TypedLong<Product>,
    val quantity: TypedInt<Product>,
    val priceInCents: TypedLong<Cents>
)

data class FruitBasket(
    val bananas: TypedInt<Banana>,
    val apples: TypedInt<Apple>
)

4. Enjoy Type Safety

The compiler now prevents mixing up values:

kotlin
// Can't mix different IDs
fun findUser(id: TypedString<User>): User? { ... }
val userId = "user-123".toTypedString<User>()
val productId = 42L.toTypedLong<Product>()

findUser(userId)     // ✅ OK
findUser(productId)  // ❌ Compilation error!

// Can't mix different quantities
fun addBananas(count: TypedInt<Banana>) { ... }
val bananas = 5.toTypedInt<Banana>()
val apples = 3.toTypedInt<Apple>()

addBananas(bananas)  // ✅ OK
addBananas(apples)   // ❌ Compilation error!

Choosing the Right Type

TypeValue TypeUse CasesExample
TypedString<T>StringIDs, emails, codes, slugs"user-abc123"
TypedLong<T>LongLarge IDs, money (cents), timestamps1234567890L
TypedInt<T>IntQuantities, small counts, indexes42
TypedUuid<T>UUIDDistributed IDs (JVM only)UUID.randomUUID()

Adding Framework Integrations

For full-stack applications, add the integration modules you need. Using the BOM is the recommended approach:

kotlin
dependencies {
    implementation(platform("com.ekino.oss:typed-value-bom:1.3.0"))

    // Core (required)
    implementation("com.ekino.oss:typed-value-core")

    // JSON serialization
    implementation("com.ekino.oss:typed-value-jackson")

    // Spring MVC support
    implementation("com.ekino.oss:typed-value-spring")

    // QueryDSL support
    implementation("com.ekino.oss:typed-value-querydsl")

    // Hibernate/JPA support
    implementation("com.ekino.oss:typed-value-hibernate")

    // Elasticsearch support
    implementation("com.ekino.oss:typed-value-spring-data-elasticsearch")
}
kotlin
dependencies {
    // Core (required)
    implementation("com.ekino.oss:typed-value-core:1.3.0")

    // JSON serialization
    implementation("com.ekino.oss:typed-value-jackson:1.3.0")

    // Spring MVC support
    implementation("com.ekino.oss:typed-value-spring:1.3.0")

    // QueryDSL support
    implementation("com.ekino.oss:typed-value-querydsl:1.3.0")

    // Hibernate/JPA support
    implementation("com.ekino.oss:typed-value-hibernate:1.3.0")

    // Elasticsearch support
    implementation("com.ekino.oss:typed-value-spring-data-elasticsearch:1.3.0")
}

See the Integrations section for detailed setup instructions.

Next Steps

Released under the MIT License.