{ lib }: # Simple internal type checks for meta. # This file is not a stable interface and may be changed arbitrarily. # # TODO: add a method to the module system types # see https://github.com/NixOS/nixpkgs/pull/273935#issuecomment-1854173100 let inherit (builtins) isString isInt isAttrs isList all any attrValues isFunction isBool concatStringsSep isFloat; isTypeDef = t: isAttrs t && t ? name && isString t.name && t ? verify && isFunction t.verify; in lib.fix (self: { string = { name = "string"; verify = isString; }; str = self.string; # Type alias any = { name = "any"; verify = _: true; }; int = { name = "int"; verify = isInt; }; float = { name = "float"; verify = isFloat; }; bool = { name = "bool"; verify = isBool; }; attrs = { name = "attrs"; verify = isAttrs; }; list = { name = "list"; verify = isList; }; attrsOf = t: assert isTypeDef t; let inherit (t) verify; in { name = "attrsOf<${t.name}>"; verify = # attrsOf can be optimised to just isAttrs if t == self.any then isAttrs else attrs: isAttrs attrs && all verify (attrValues attrs); }; listOf = t: assert isTypeDef t; let inherit (t) verify; in { name = "listOf<${t.name}>"; verify = # listOf can be optimised to just isList if t == self.any then isList else v: isList v && all verify v; }; union = types: assert all isTypeDef types; let # Store a list of functions so we don't have to pay the cost of attrset lookups at runtime. funcs = map (t: t.verify) types; in { name = "union<${concatStringsSep "," (map (t: t.name) types)}>"; verify = v: any (func: func v) funcs; }; })