adisbladis/korora
{ "createdAt": "2023-12-14T11:20:54Z", "defaultBranch": "master", "description": "A tiny & fast type system for Nix in Nix", "fullName": "adisbladis/korora", "homepage": "", "language": "Nix", "name": "korora", "pushedAt": "2025-11-15T08:37:33Z", "stargazersCount": 93, "topics": [], "updatedAt": "2025-11-15T08:37:36Z", "url": "https://github.com/adisbladis/korora"}Kororā
Section titled “Kororā”A tiny & fast composable type system for Nix, in Nix.
Named after the little penguin.
Features
Section titled “Features”- Types
- Primitive types (
string,int, etc) - Polymorphic types (
union,attrsOf, etc) - Struct types
- Primitive types (
Basic usage
Section titled “Basic usage”- Verification
Basic verification is done with the type function verify:
{ korora }:let t = korora.string;
value = 1;
# Error contains the string "Expected type 'string' but value '1' is of type 'int'" error = t.verify 1;
in if error != null then throw error else valueErrors are returned as a string.
On success null is returned.
- Checking (assertions)
For convenience you can also check a value on-the-fly:
{ korora }:let t = korora.string;
value = 1;
# Same error as previous example, but `check` throws. value = t.check value value;
in valueOn error check throws. On success it returns the value that was passed in.
Examples
Section titled “Examples”For usage example see [tests.nix]!(./tests.nix).
Reference
Section titled “Reference”lib.types.typedef
Section titled “lib.types.typedef”Declare a custom type using a bool function
name
: Name of the type as a string
verify
: Verification function returning a bool.
lib.types.typedef'
Section titled “lib.types.typedef'”Declare a custom type using an option
name
: Name of the type as a string
verify
: Verification function returning null on success & a string with error message on error.
lib.types.string
Section titled “lib.types.string”String
lib.types.str
Section titled “lib.types.str”Type alias for string
lib.types.any
Section titled “lib.types.any”Any
lib.types.never
Section titled “lib.types.never”Never
lib.types.int
Section titled “lib.types.int”Int
lib.types.float
Section titled “lib.types.float”Single precision floating point
lib.types.number
Section titled “lib.types.number”Either an int or a float
lib.types.bool
Section titled “lib.types.bool”Bool
lib.types.attrs
Section titled “lib.types.attrs”Attribute with undefined attribute types
lib.types.list
Section titled “lib.types.list”Attribute with undefined element types
lib.types.function
Section titled “lib.types.function”Function
lib.types.path
Section titled “lib.types.path”Path
lib.types.derivation
Section titled “lib.types.derivation”Derivation
lib.types.type
Section titled “lib.types.type”Type
lib.types.option
Section titled “lib.types.option”Option
t
: Null or t
lib.types.listOf
Section titled “lib.types.listOf”listOf
t
: Element type
lib.types.attrsOf
Section titled “lib.types.attrsOf”listOf
t
: Attribute value type
lib.types.union
Section titled “lib.types.union”union<types…>
types
: Any of
lib.types.intersection
Section titled “lib.types.intersection”intersection<types…>
types
: All of
lib.types.rename
Section titled “lib.types.rename”rename<name, type>
Because some polymorphic types such as attrsOf inherits names from it’s sub-types we need to erase the name to not cause infinite recursion.
Example:
Section titled “Example:”myType = types.attrsOf ( types.rename "eitherType" (types.union [ types.string myType ]));name
: Function argument
type
: Function argument
lib.types.struct
Section titled “lib.types.struct”struct<name, members…>
Example
Section titled “Example”korora.struct "myStruct" { foo = types.string;}Features
Section titled “Features”- Totality
By default, all attribute names must be present in a struct. It is possible to override this by specifying totality. Here is how to do this:
(korora.struct "myStruct" { foo = types.string;}).override { total = false; }This means that a myStruct struct can have any of the keys omitted. Thus these are valid:
let s1 = { }; s2 = { foo = "bar"; }in ...- Unknown attribute names
By default, unknown attribute names are allowed.
It is possible to override this by specifying unknown.
(korora.struct "myStruct" { foo = types.string;}).override { unknown = false; }This means that
{ foo = "bar"; baz = "hello";}is normally valid, but not when unknown is set to false.
Because Nix lacks primitive operations to iterate over attribute sets dynamically without allocation this function allocates one intermediate attribute set per struct verification.
- Custom invariants
Custom struct verification functions can be added as such:
(types.struct "testStruct2" { x = types.int; y = types.int;}).override { verify = v: if v.x + v.y == 2 then "VERBOTEN" else null;};Function signature
Section titled “Function signature”name
: Name of struct type as a string
members
: Attribute set of type definitions.
lib.types.optionalAttr
Section titled “lib.types.optionalAttr”optionalAttr
t
: Function argument
lib.types.enum
Section titled “lib.types.enum”enum<name, elems…>
name
: Name of enum type as a string
elems
: List of allowable enum members
lib.types.defun
Section titled “lib.types.defun”defun<name, args, returns, function>
Example
Section titled “Example”let wrappedFunc = types.defun "fn" [ types.str ] types.str (s: s + "-checked");in # Returns "foo-checked" wrappedfunc "foo"