Unverified Commit 9d3e6499 authored by Johannes Kirschbauer's avatar Johannes Kirschbauer Committed by GitHub
Browse files

lib.types: init mergeTypes (#364620)

parents 04757606 3c911b2a
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -2612,4 +2612,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 = types.isType "merge-error" mergedType;
    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;
    };
  };
}
+47 −0
Original line number Diff line number Diff line
@@ -1125,6 +1125,53 @@ 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.
    - `{ _type = "merge-error"; error = "Cannot merge types"; }` 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
      setType "merge-error" { error = "Cannot merge types"; }
    else
      merged;
};

in outer_types // outer_types.types