neotype
A friendly newtype library for Scala 3.
"io.github.kitlangton" %% "neotype" % "0.1.0"
Features
- Compile-time Checked Values
- Write validations as plain, old Scala expressions
- Very Helpful Error Messages (see below)
- No Runtime Allocations (Thanks to
inline
andopaque type
) - Ability to integrate with other libraries (e.g.
zio-json
,circe
, etc.)
Example
import neotype.*
// Define a newtype:
given NonEmptyString: Newtype[String] with
// Hey, a plain old Scala expression!
inline def validate(input: String): Boolean =
input.nonEmpty
// Wrap values, which checked at compile-time:
NonEmptyString("Hello") // OK
NonEmptyString("") // Compile Error
Error: /Users/kit/code/neotype/examples/src/main/scala/neotype/examples/Main.scala:9:16
NonEmptyString("")
^^^^^^^^^^^^^^^^^^
—— Newtype Error ——————————————————————————————————————————————————————————
NonEmptyString was called with an INVALID String.
input: ""
check: input.nonEmpty
———————————————————————————————————————————————————————————————————————————
Integrations
Neotype integrates with the following libraries.
- zio-json
- zio-config
- tapir
- quill
- circe
ZIO Json Example
import neotype.*
import neotype.ziojson.*
import zio.json.*
type NonEmptyString = NonEmptyString.Type
given NonEmptyString: Newtype[String] with
inline def validate(value: String): Boolean = value.nonEmpty
override inline def failureMessage = "String must not be empty"
case class Person(name: NonEmptyString, age: Int) derives JsonCodec
val parsed = """{"name": "Kit", "age": 30}""".fromJson[Person]
// Right(Person(NonEmptyString("Kit"), 30))
val failed = """{"name": "", "age": 30}""".fromJson[Person]
// Left(".name(String must not be empty)")
By importing neotype.ziojson.*
, we automatically generate a JsonCodec
for NonEmptyString
. Custom
failure messages are also supported (by overriding def failureMessage
in the Newtype definition).