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

lib.types: init mergeTypes #364620

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
41 changes: 41 additions & 0 deletions lib/tests/misc.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2564,4 +2564,45 @@ runTests {
};
expected = "c";
};

testMergeTypesSimple =
let
mergedType = types.mergeTypes types.str types.str;
in
{
expr = mergedType.name;
expected = "str";
};

testMergeTypesFail =
let
mergedType = types.mergeTypes types.str types.int;
in
{
expr = mergedType ? error;
expected = true;
};

testMergeTypesEnum =
let
enumAB = lib.types.enum ["A" "B"];
enumXY = lib.types.enum ["X" "Y"];
merged = lib.types.mergeTypes enumAB enumXY; # -> enum [ "A" "B" "X" "Y" ]
in
{
expr = {
checkA = merged.check "A";
checkB = merged.check "B";
checkX = merged.check "X";
checkY = merged.check "Y";
checkC = merged.check "C";
};
expected = {
checkA = true;
checkB = true;
checkX = true;
checkY = true;
checkC = false;
};
};
}
43 changes: 43 additions & 0 deletions lib/types.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,49 @@ rec {
addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; };

};

/**
Merges two option types together.

:::{.note}
Uses the type merge function of the first type, to merge it with the second type.

Usually types can only be merged if they are of the same type
:::

# Inputs

: `a` (option type): The first option type.
: `b` (option type): The second option type.

# Returns

- The merged option type.
- `{ error = "Some Message String"; }` if the types can't be merged.

# Examples
:::{.example}
## `lib.types.mergeTypes` usage example
```nix
let
enumAB = lib.types.enum ["A" "B"];
enumXY = lib.types.enum ["X" "Y"];
# This operation could be notated as: [ A ] | [ B ] -> [ A B ]
merged = lib.types.mergeTypes enumAB enumXY; # -> enum [ "A" "B" "X" "Y" ]
in
assert merged.check "A"; # true
assert merged.check "B"; # true
assert merged.check "X"; # true
assert merged.check "Y"; # true
merged.check "C" # false
```
:::
*/
mergeTypes = a: b:
assert isOptionType a && isOptionType b;
let
merged = a.typeMerge b.functor;
in if merged == null then { error = "Cannot merge types"; } else merged;
};

in outer_types // outer_types.types