/**
 * A type mapping interface that enables incremental type-level arithmetic operations.
 * This interface maps each number from 0 to 32,767 to its successor (n + 1),
 * enabling compile-time numeric operations in TypeScript's type system.
 *
 * @remarks
 * This interface is primarily used as a helper for other type utilities that need
 * to perform incremental operations, such as the `PositiveRange` type utility.
 * The mapping is limited to numbers up to 32,768 due to TypeScript's computational limits.
 *
 * @example
 * ```typescript
 * type Next = NumberMap[5]; // Results in: 6
 * type Invalid = NumberMap[32769]; // Results in: never
 * ```
 *
 * @internal
 * This interface is not intended to be used directly by consumers of the library.
 */
interface NumberMap {
    0: 1;
    1: 2;
    2: 3;
    3: 4;
    4: 5;
    5: 6;
    6: 7;
    7: 8;
    8: 9;
    9: 10;
    10: 11;
    11: 12;
    12: 13;
    13: 14;
    14: 15;
    15: 16;
    16: 17;
    17: 18;
    18: 19;
    19: 20;
    20: 21;
    21: 22;
    22: 23;
    23: 24;
    24: 25;
    25: 26;
    26: 27;
    27: 28;
    28: 29;
    29: 30;
    30: 31;
    31: 32;
    32: 33;
    33: 34;
    34: 35;
    35: 36;
    36: 37;
    37: 38;
    38: 39;
    39: 40;
    40: 41;
    41: 42;
    42: 43;
    43: 44;
    44: 45;
    45: 46;
    46: 47;
    47: 48;
    48: 49;
    49: 50;
    50: 51;
    51: 52;
    52: 53;
    53: 54;
    54: 55;
    55: 56;
    56: 57;
    57: 58;
    58: 59;
    59: 60;
    60: 61;
    61: 62;
    62: 63;
    63: 64;
    64: 65;
    65: 66;
    66: 67;
    67: 68;
    68: 69;
    69: 70;
    70: 71;
    71: 72;
    72: 73;
    73: 74;
    74: 75;
    75: 76;
    76: 77;
    77: 78;
    78: 79;
    79: 80;
    80: 81;
    81: 82;
    82: 83;
    83: 84;
    84: 85;
    85: 86;
    86: 87;
    87: 88;
    88: 89;
    89: 90;
    90: 91;
    91: 92;
    92: 93;
    93: 94;
    94: 95;
    95: 96;
    96: 97;
    97: 98;
    98: 99;
    99: 100;
    100: 101;
    101: 102;
    102: 103;
    103: 104;
    104: 105;
    105: 106;
    106: 107;
    107: 108;
    108: 109;
    109: 110;
    110: 111;
    111: 112;
    112: 113;
    113: 114;
    114: 115;
    115: 116;
    116: 117;
    117: 118;
    118: 119;
    119: 120;
    120: 121;
    121: 122;
    122: 123;
    123: 124;
    124: 125;
    125: 126;
    126: 127;
    127: 128;
    128: 129;
    129: 130;
    130: 131;
    131: 132;
    132: 133;
    133: 134;
    134: 135;
    135: 136;
    136: 137;
    137: 138;
    138: 139;
    139: 140;
    140: 141;
    141: 142;
    142: 143;
    143: 144;
    144: 145;
    145: 146;
    146: 147;
    147: 148;
    148: 149;
    149: 150;
    150: 151;
    151: 152;
    152: 153;
    153: 154;
    154: 155;
    155: 156;
    156: 157;
    157: 158;
    158: 159;
    159: 160;
    160: 161;
    161: 162;
    162: 163;
    163: 164;
    164: 165;
    165: 166;
    166: 167;
    167: 168;
    168: 169;
    169: 170;
    170: 171;
    171: 172;
    172: 173;
    173: 174;
    174: 175;
    175: 176;
    176: 177;
    177: 178;
    178: 179;
    179: 180;
    180: 181;
    181: 182;
    182: 183;
    183: 184;
    184: 185;
    185: 186;
    186: 187;
    187: 188;
    188: 189;
    189: 190;
    190: 191;
    191: 192;
    192: 193;
    193: 194;
    194: 195;
    195: 196;
    196: 197;
    197: 198;
    198: 199;
    199: 200;
    200: 201;
    201: 202;
    202: 203;
    203: 204;
    204: 205;
    205: 206;
    206: 207;
    207: 208;
    208: 209;
    209: 210;
    210: 211;
    211: 212;
    212: 213;
    213: 214;
    214: 215;
    215: 216;
    216: 217;
    217: 218;
    218: 219;
    219: 220;
    220: 221;
    221: 222;
    222: 223;
    223: 224;
    224: 225;
    225: 226;
    226: 227;
    227: 228;
    228: 229;
    229: 230;
    230: 231;
    231: 232;
    232: 233;
    233: 234;
    234: 235;
    235: 236;
    236: 237;
    237: 238;
    238: 239;
    239: 240;
    240: 241;
    241: 242;
    242: 243;
    243: 244;
    244: 245;
    245: 246;
    246: 247;
    247: 248;
    248: 249;
    249: 250;
    250: 251;
    251: 252;
    252: 253;
    253: 254;
    254: 255;
    255: 256;
    256: 257;
    257: 258;
    258: 259;
    259: 260;
    260: 261;
    261: 262;
    262: 263;
    263: 264;
    264: 265;
    265: 266;
    266: 267;
    267: 268;
    268: 269;
    269: 270;
    270: 271;
    271: 272;
    272: 273;
    273: 274;
    274: 275;
    275: 276;
    276: 277;
    277: 278;
    278: 279;
    279: 280;
    280: 281;
    281: 282;
    282: 283;
    283: 284;
    284: 285;
    285: 286;
    286: 287;
    287: 288;
    288: 289;
    289: 290;
    290: 291;
    291: 292;
    292: 293;
    293: 294;
    294: 295;
    295: 296;
    296: 297;
    297: 298;
    298: 299;
    299: 300;
    300: 301;
    301: 302;
    302: 303;
    303: 304;
    304: 305;
    305: 306;
    306: 307;
    307: 308;
    308: 309;
    309: 310;
    310: 311;
    311: 312;
    312: 313;
    313: 314;
    314: 315;
    315: 316;
    316: 317;
    317: 318;
    318: 319;
    319: 320;
    320: 321;
    321: 322;
    322: 323;
    323: 324;
    324: 325;
    325: 326;
    326: 327;
    327: 328;
    328: 329;
    329: 330;
    330: 331;
    331: 332;
    332: 333;
    333: 334;
    334: 335;
    335: 336;
    336: 337;
    337: 338;
    338: 339;
    339: 340;
    340: 341;
    341: 342;
    342: 343;
    343: 344;
    344: 345;
    345: 346;
    346: 347;
    347: 348;
    348: 349;
    349: 350;
    350: 351;
    351: 352;
    352: 353;
    353: 354;
    354: 355;
    355: 356;
    356: 357;
    357: 358;
    358: 359;
    359: 360;
    360: 361;
    361: 362;
    362: 363;
    363: 364;
    364: 365;
    365: 366;
    366: 367;
    367: 368;
    368: 369;
    369: 370;
    370: 371;
    371: 372;
    372: 373;
    373: 374;
    374: 375;
    375: 376;
    376: 377;
    377: 378;
    378: 379;
    379: 380;
    380: 381;
    381: 382;
    382: 383;
    383: 384;
    384: 385;
    385: 386;
    386: 387;
    387: 388;
    388: 389;
    389: 390;
    390: 391;
    391: 392;
    392: 393;
    393: 394;
    394: 395;
    395: 396;
    396: 397;
    397: 398;
    398: 399;
    399: 400;
    400: 401;
    401: 402;
    402: 403;
    403: 404;
    404: 405;
    405: 406;
    406: 407;
    407: 408;
    408: 409;
    409: 410;
    410: 411;
    411: 412;
    412: 413;
    413: 414;
    414: 415;
    415: 416;
    416: 417;
    417: 418;
    418: 419;
    419: 420;
    420: 421;
    421: 422;
    422: 423;
    423: 424;
    424: 425;
    425: 426;
    426: 427;
    427: 428;
    428: 429;
    429: 430;
    430: 431;
    431: 432;
    432: 433;
    433: 434;
    434: 435;
    435: 436;
    436: 437;
    437: 438;
    438: 439;
    439: 440;
    440: 441;
    441: 442;
    442: 443;
    443: 444;
    444: 445;
    445: 446;
    446: 447;
    447: 448;
    448: 449;
    449: 450;
    450: 451;
    451: 452;
    452: 453;
    453: 454;
    454: 455;
    455: 456;
    456: 457;
    457: 458;
    458: 459;
    459: 460;
    460: 461;
    461: 462;
    462: 463;
    463: 464;
    464: 465;
    465: 466;
    466: 467;
    467: 468;
    468: 469;
    469: 470;
    470: 471;
    471: 472;
    472: 473;
    473: 474;
    474: 475;
    475: 476;
    476: 477;
    477: 478;
    478: 479;
    479: 480;
    480: 481;
    481: 482;
    482: 483;
    483: 484;
    484: 485;
    485: 486;
    486: 487;
    487: 488;
    488: 489;
    489: 490;
    490: 491;
    491: 492;
    492: 493;
    493: 494;
    494: 495;
    495: 496;
    496: 497;
    497: 498;
    498: 499;
    499: 500;
    500: 501;
    501: 502;
    502: 503;
    503: 504;
    504: 505;
    505: 506;
    506: 507;
    507: 508;
    508: 509;
    509: 510;
    510: 511;
    511: 512;
    512: 513;
    513: 514;
    514: 515;
    515: 516;
    516: 517;
    517: 518;
    518: 519;
    519: 520;
    520: 521;
    521: 522;
    522: 523;
    523: 524;
    524: 525;
    525: 526;
    526: 527;
    527: 528;
    528: 529;
    529: 530;
    530: 531;
    531: 532;
    532: 533;
    533: 534;
    534: 535;
    535: 536;
    536: 537;
    537: 538;
    538: 539;
    539: 540;
    540: 541;
    541: 542;
    542: 543;
    543: 544;
    544: 545;
    545: 546;
    546: 547;
    547: 548;
    548: 549;
    549: 550;
    550: 551;
    551: 552;
    552: 553;
    553: 554;
    554: 555;
    555: 556;
    556: 557;
    557: 558;
    558: 559;
    559: 560;
    560: 561;
    561: 562;
    562: 563;
    563: 564;
    564: 565;
    565: 566;
    566: 567;
    567: 568;
    568: 569;
    569: 570;
    570: 571;
    571: 572;
    572: 573;
    573: 574;
    574: 575;
    575: 576;
    576: 577;
    577: 578;
    578: 579;
    579: 580;
    580: 581;
    581: 582;
    582: 583;
    583: 584;
    584: 585;
    585: 586;
    586: 587;
    587: 588;
    588: 589;
    589: 590;
    590: 591;
    591: 592;
    592: 593;
    593: 594;
    594: 595;
    595: 596;
    596: 597;
    597: 598;
    598: 599;
    599: 600;
    600: 601;
    601: 602;
    602: 603;
    603: 604;
    604: 605;
    605: 606;
    606: 607;
    607: 608;
    608: 609;
    609: 610;
    610: 611;
    611: 612;
    612: 613;
    613: 614;
    614: 615;
    615: 616;
    616: 617;
    617: 618;
    618: 619;
    619: 620;
    620: 621;
    621: 622;
    622: 623;
    623: 624;
    624: 625;
    625: 626;
    626: 627;
    627: 628;
    628: 629;
    629: 630;
    630: 631;
    631: 632;
    632: 633;
    633: 634;
    634: 635;
    635: 636;
    636: 637;
    637: 638;
    638: 639;
    639: 640;
    640: 641;
    641: 642;
    642: 643;
    643: 644;
    644: 645;
    645: 646;
    646: 647;
    647: 648;
    648: 649;
    649: 650;
    650: 651;
    651: 652;
    652: 653;
    653: 654;
    654: 655;
    655: 656;
    656: 657;
    657: 658;
    658: 659;
    659: 660;
    660: 661;
    661: 662;
    662: 663;
    663: 664;
    664: 665;
    665: 666;
    666: 667;
    667: 668;
    668: 669;
    669: 670;
    670: 671;
    671: 672;
    672: 673;
    673: 674;
    674: 675;
    675: 676;
    676: 677;
    677: 678;
    678: 679;
    679: 680;
    680: 681;
    681: 682;
    682: 683;
    683: 684;
    684: 685;
    685: 686;
    686: 687;
    687: 688;
    688: 689;
    689: 690;
    690: 691;
    691: 692;
    692: 693;
    693: 694;
    694: 695;
    695: 696;
    696: 697;
    697: 698;
    698: 699;
    699: 700;
    700: 701;
    701: 702;
    702: 703;
    703: 704;
    704: 705;
    705: 706;
    706: 707;
    707: 708;
    708: 709;
    709: 710;
    710: 711;
    711: 712;
    712: 713;
    713: 714;
    714: 715;
    715: 716;
    716: 717;
    717: 718;
    718: 719;
    719: 720;
    720: 721;
    721: 722;
    722: 723;
    723: 724;
    724: 725;
    725: 726;
    726: 727;
    727: 728;
    728: 729;
    729: 730;
    730: 731;
    731: 732;
    732: 733;
    733: 734;
    734: 735;
    735: 736;
    736: 737;
    737: 738;
    738: 739;
    739: 740;
    740: 741;
    741: 742;
    742: 743;
    743: 744;
    744: 745;
    745: 746;
    746: 747;
    747: 748;
    748: 749;
    749: 750;
    750: 751;
    751: 752;
    752: 753;
    753: 754;
    754: 755;
    755: 756;
    756: 757;
    757: 758;
    758: 759;
    759: 760;
    760: 761;
    761: 762;
    762: 763;
    763: 764;
    764: 765;
    765: 766;
    766: 767;
    767: 768;
    768: 769;
    769: 770;
    770: 771;
    771: 772;
    772: 773;
    773: 774;
    774: 775;
    775: 776;
    776: 777;
    777: 778;
    778: 779;
    779: 780;
    780: 781;
    781: 782;
    782: 783;
    783: 784;
    784: 785;
    785: 786;
    786: 787;
    787: 788;
    788: 789;
    789: 790;
    790: 791;
    791: 792;
    792: 793;
    793: 794;
    794: 795;
    795: 796;
    796: 797;
    797: 798;
    798: 799;
    799: 800;
    800: 801;
    801: 802;
    802: 803;
    803: 804;
    804: 805;
    805: 806;
    806: 807;
    807: 808;
    808: 809;
    809: 810;
    810: 811;
    811: 812;
    812: 813;
    813: 814;
    814: 815;
    815: 816;
    816: 817;
    817: 818;
    818: 819;
    819: 820;
    820: 821;
    821: 822;
    822: 823;
    823: 824;
    824: 825;
    825: 826;
    826: 827;
    827: 828;
    828: 829;
    829: 830;
    830: 831;
    831: 832;
    832: 833;
    833: 834;
    834: 835;
    835: 836;
    836: 837;
    837: 838;
    838: 839;
    839: 840;
    840: 841;
    841: 842;
    842: 843;
    843: 844;
    844: 845;
    845: 846;
    846: 847;
    847: 848;
    848: 849;
    849: 850;
    850: 851;
    851: 852;
    852: 853;
    853: 854;
    854: 855;
    855: 856;
    856: 857;
    857: 858;
    858: 859;
    859: 860;
    860: 861;
    861: 862;
    862: 863;
    863: 864;
    864: 865;
    865: 866;
    866: 867;
    867: 868;
    868: 869;
    869: 870;
    870: 871;
    871: 872;
    872: 873;
    873: 874;
    874: 875;
    875: 876;
    876: 877;
    877: 878;
    878: 879;
    879: 880;
    880: 881;
    881: 882;
    882: 883;
    883: 884;
    884: 885;
    885: 886;
    886: 887;
    887: 888;
    888: 889;
    889: 890;
    890: 891;
    891: 892;
    892: 893;
    893: 894;
    894: 895;
    895: 896;
    896: 897;
    897: 898;
    898: 899;
    899: 900;
    900: 901;
    901: 902;
    902: 903;
    903: 904;
    904: 905;
    905: 906;
    906: 907;
    907: 908;
    908: 909;
    909: 910;
    910: 911;
    911: 912;
    912: 913;
    913: 914;
    914: 915;
    915: 916;
    916: 917;
    917: 918;
    918: 919;
    919: 920;
    920: 921;
    921: 922;
    922: 923;
    923: 924;
    924: 925;
    925: 926;
    926: 927;
    927: 928;
    928: 929;
    929: 930;
    930: 931;
    931: 932;
    932: 933;
    933: 934;
    934: 935;
    935: 936;
    936: 937;
    937: 938;
    938: 939;
    939: 940;
    940: 941;
    941: 942;
    942: 943;
    943: 944;
    944: 945;
    945: 946;
    946: 947;
    947: 948;
    948: 949;
    949: 950;
    950: 951;
    951: 952;
    952: 953;
    953: 954;
    954: 955;
    955: 956;
    956: 957;
    957: 958;
    958: 959;
    959: 960;
    960: 961;
    961: 962;
    962: 963;
    963: 964;
    964: 965;
    965: 966;
    966: 967;
    967: 968;
    968: 969;
    969: 970;
    970: 971;
    971: 972;
    972: 973;
    973: 974;
    974: 975;
    975: 976;
    976: 977;
    977: 978;
    978: 979;
    979: 980;
    980: 981;
    981: 982;
    982: 983;
    983: 984;
    984: 985;
    985: 986;
    986: 987;
    987: 988;
    988: 989;
    989: 990;
    990: 991;
    991: 992;
    992: 993;
    993: 994;
    994: 995;
    995: 996;
    996: 997;
    997: 998;
    998: 999;
}

/**
 * Used to display an error message instead of never, for better readability
 * @export type {UnassignableTypeError}
 */
type UnassignableTypeError<ErrType extends string> = `type is not assignable to type ${ErrType}`;
/**
 *
 * Represents a type that can either be  ``null`` or ``undefined``.
 * @export type {Nullable}
 */
type Nullable = null | undefined;
/**
 * Represents a  type that can hold any numeric value: number or a bigint.
 * @export type {Numeric}
 */
type Numeric = number | bigint;
/**
 * Represents all the primitive types in JavaScript.
 * - `Nullable`: A value that can be either null or undefined.
 * - `Numeric`: A value that can be either a number or a bigint.
 * - `string`: Represents textual data.
 * - `boolean`: Represents a logical value (true or false).
 * - `symbol`: Represents a unique and immutable value.
 */
type Primitive = string | boolean | symbol | Nullable | Numeric;
/**
 * Represents a type that includes falsy values in JavaScript.
 * Falsy values are those that coerce to false when used in a boolean context.
 * This includes `false`, an empty string (`''`), numeric zero (`0`), `null`,
 * and `undefined`.
 */
type Falsy = false | '' | 0 | Nullable;
/**
 * This type is used to describe constructor functions or classes
 * that can be invoked using the `new` keyword.
 */
type Newable = {
    new (...args: any[]): any;
};
/**
 * Describes any function accepting any arguments
 *  and returning any value.
 */
type AnyFunction = (...args: any[]) => any;
/**
 * Describes any function accepting and retruning `unknown`s
 */
type UnknownFunction = (...args: unknown[]) => unknown;
/**
 * Represents an integer type.
 * This type is used to ensure that a numeric value is an integer.
 *
 * Example use case:
 *
 * ```ts
 * export function myFunc<T extends Numeric>(a: Integer<T>) {
 *   console.log(a);
 * }
 * const good = myFunc(4545); // This is valid as 4545 is an integer.
 * const bad = myFunc(4545.554); // This will throw an error as 4545.554 is not an integer.
 * ```
 */
type Integer<N extends Numeric> = IfEquals<IsInteger<N>, true, N, never>;
/**
 * Type representing an integer that's in [0,+∞[
 */
type PositiveInteger<N extends Numeric> = IfEquals<IsPositiveInteger<N>, true, Integer<N>, never>;
/**
 * Represents a positive integer parsed from a string.
 * If the string does not represent a positive integer, it resolves to `never`, else
 * it resolves to its integer representation.
 * @example
 * ````ts
    PositiveIntegerString<'0'>; // works
    PositiveIntegerString<'82739283293237'>; // works
    PositiveIntegerString<'82739.283293237'>; // never
    PositiveIntegerString<'-82739.283293237'>; // never
    PositiveIntegerString<'-1'>; // never
 * ````
 */
type PositiveIntegerString<S extends string> = IfEquals<IsPositiveInteger<Integer<NumerifyString<S>>>, true, Integer<NumerifyString<S>>, never>;
/**
 * Type representing an integer that's in ]-∞, 0[
 */
type NegativeInteger<N extends Numeric> = IfEquals<IsNegativeInteger<N>, true, Integer<N>, never>;
/**
 * Represents a negative integer parsed from a string.
 * If the string does not represent a negative integer, it resolves to `never`, else
 * it resolves to its integer representation.
 * @example
 * ````ts
    NegativeIntegerString<'0'>; // never
    NegativeIntegerString<'82739283293237'>; // never
    NegativeIntegerString<'-82739.283293237'>; // works
    NegativeIntegerString<'-82739.283293237'>; // never
    NegativeIntegerString<'-1'>; // works
 * ````
 */
type NegativeIntegerString<S extends string> = IfEquals<IsNegativeInteger<Integer<NumerifyString<S>>>, true, Integer<NumerifyString<S>>, never>;
/**
 * Is it a negative integer ?
 * @return
 * `true` if it is, else `false`
 */
type IsNegativeInteger<N extends Numeric> = IsNegative<Integer<N>>;
/**
 * Is it a positive integer ?
 * @return
 * `true` if it is, else `false`
 */
type IsPositiveInteger<N extends Numeric> = IsPositive<Integer<N>>;
/**
 * Type representing a float
 */
type Float<N extends Numeric> = IfExtends<IsFloat<N>, true, N, never>;
/**
 * Type representing a float that's in [0,+∞[
 */
type PositiveFloat<N extends Numeric> = IfEquals<IsPositiveFloat<N>, true, Float<N>, never>;
/**
 * Represents a positive float parsed from a string.
 * If the string does not represent a positive float, it resolves to `never`, else
 * it resolves to its float representation.
 * @example
 * ````ts
    PositiveFloatString<'0'>; // never
    PositiveFloatString<'82739283293237'>; // works
    PositiveFloatString<'-82739.283293237'>; // never
    PositiveFloatString<'-1'>; // never
    PositiveFloatString<'1.98'>; // works
    PositiveFloatString<'-1.98'>; // never
 * ````
 */
type PositiveFloatString<S extends string> = IfEquals<IsPositiveFloat<Float<NumerifyString<S>>>, true, Float<NumerifyString<S>>, never>;
/**
 * Type representing a float that's in ]-∞, 0[
 */
type NegativeFloat<N extends Numeric> = IfEquals<IsNegativeFloat<N>, true, Float<N>, never>;
/**
 * Represents a negative float parsed from a string.
 * If the string does not represent a negative float, it resolves to `never`, else
 * it resolves to its float representation.
 * @example
 * ````ts
    NegativeFloatString<'0'>; // never
    NegativeFloatString<'82739283293237'>; // never
    NegativeFloatString<'-82739.283293237'>; // works
    NegativeFloatString<'-1'>; // never
    NegativeFloatString<'-1.98'>; // works
 * ````
 */
type NegativeFloatString<S extends string> = IfEquals<IsNegativeFloat<Float<NumerifyString<S>>>, true, Float<NumerifyString<S>>, never>;
/**
 * Is it a negative float ?
 * @return
 * `true` if it is, else `false`
 */
type IsNegativeFloat<N extends Numeric> = IsNegative<Float<N>>;
/**
 * Is it a positive float ?
 * @return
 * `true` if it is, else `false`
 */
type IsPositiveFloat<N extends Numeric> = IsPositive<Float<N>>;
/**
 * Represents an odd numeric?
 * @example
 * ````ts
 * Odd<2587967>; // 2587967
 * Odd<215848141>; // 215848141
 * Odd<200000000000000>; // never
 * Odd<200000000000000.55>; // never
 * Odd<200000000000001.53>; // never
 * ````
 */
type Odd<T extends Numeric> = IfExtends<StringifyPrimitive<Integer<T>>, `${Numeric | ''}${1 | 3 | 5 | 7 | 9}`, T, never>;
/**
 * Represents an even numeric
 * @example
 * ````ts
 * Even<200000000000000>; // 258796
 * Even<258796>; // 258796
 * Even<2000000000000001>; // never
 * ````
 */
type Even<T extends Numeric> = IfExtends<StringifyPrimitive<Integer<T>>, `${Numeric | ''}${2 | 4 | 6 | 8 | 0}`, T, never>;
/**
 * `Optional<T>` is similar to Python's `Optional` and Rust's `Option` types.
 * It promotes more predictable code,
 * by enforcing explicit handling of optional scenarios, e.g: requiring functions
 * to return `null` specifically when a value is absent.
 */
type Optional<T> = T | null;
/**
 Represnets a type that might be nullable, as in it might be `null` or `undefined`.
*/
type Maybe<T> = T | Nullable;
type MaybeUnknown<T> = T | unknown;
type MaybeUndefined<T> = T | undefined;
/**
 * Presents any non-nullish value
 */
type EmptyObject = NonNullable<unknown>;
/**
 * Extracts truthy properties from an object type `T`.
 * @example
 * ````ts
type T = {
  name: string;
  age: number;
  hasCar: boolean;
  address?: string | null;
}
type R = TruthyProperties<T>;
// Result: { name: string; age: number; hasCar: boolean; }
 * ````
 */
type TruthyProperties<T> = Pick<T, {
    [K in Keys<T>]: IsTruthy<T[K]> extends true ? K : never;
}[Keys<T>]>;
/**
 * Extracts falsy properties from an object type `T`.
 * @example
 * ````ts
type T = {
  a: string;
  b: number;
  c: boolean;
  d?: string | null;
  e: 0;
  f: null;
};
type az = FalsyProperties<T>;
// Result: {
    e: 0;
    f: null;
}
 * ````
 */
type FalsyProperties<T> = Pick<T, {
    [K in Keys<T>]: IsFalsy<T[K]> extends true ? K : never;
}[Keys<T>]>;
/**
 * Checks if a given type `T` is `Falsy`.
 * @returns `true` if `T` is a subtype of `Falsy`, otherwise `false`.
 * @example
 * type Falsy = IsFalsy<''>; // TestFalsy is tru`
 * type Truthy = IsFalsy<10>; // TestTruthy is false
 */
type IsFalsy<T> = IfExtends<T, Falsy, true, false>;
/**
 * Checks if a given  type `T` is a truthy value.
 * A truthy value is any value that is not a falsy value.
 * @returns `true` if `T` is not a subtype of `Falsy`, otherwise `false`.
 * @example
 *  type TruthyString = IsTruthy<string>; // => true
 *  type TruthyNumber = IsTruthy<10>; // => true
 *  type FalsyNull = IsTruthy<null>; // => false
 *  type FalsyEmptyString = IsTruthy<''>; => false
 */
type IsTruthy<T> = IfExtends<T, Exclude<T, Falsy>, true, false>;
/**
 * Checks if a given  type `T` is `never`.
 * The `never`  type represents a value that never occurs,
 * for example a function that always errors out.
 * @returns `true` if `T` is `never`, otherwise `false`.
 * @example
 *  type Never = IsNever<never>; => true
 *  type NotNever = IsNever<string>; => false
 */
type IsNever<T> = Equals<T, never>;
/**
 * A nullable type is a type that might be null, undefined or both
 * @returns
 * `true` if it is, else `false`
 */
type IsNullable<T> = IfExtends<T, Nullable, true, false>;
/**
 * Checks if a given  type `T` is `unknown`.
 *
 * Values of  type `unknown` can hold any value, similar to `any`, but with stricter  type safety.
 * Unlike `any`, you cannot perform operations directly on values of  type `unknown`
 * without  type assertion or  type narrowing.
 * @returns `true` if `T` is `unknown`, otherwise `false`.
 * @example
 *  type IsUnknownValue = IsUnknown<unknown>; //  true
 *  type IsNotUnknownValue = IsUnknown<string>; // also true
 * @remarks
 * > If you want `unknown` to be exact, use `IsExactlyUnknown`
 */
type IsUnknown<T> = IfExtends<T, unknown, true, false>;
/**
 * Checks if a given  type `T` is exactly `unknown`.
 * @example
 * ````ts
  IsExactlyUnknown<any | unknown>; // false, since the union evaluates to any
  IsExactlyAny<any | unknown>; // true
  IsExactlyUnknown<unknown | string> // true
  IsExactlyUnknown<string>; // flase
 * ````
 */
type IsExactlyUnknown<T> = Equals<T, unknown>;
/**
 * @returns `true` if `T` is `string`, otherwise `false`.
 */
type IsString<T> = IfExtends<T, string, true, false>;
/**
 * @returns `true` if `T` is excatly `string`, otherwise `false`.
 * @example
 * ````ts
  IsExactlyString<number>; //  false;
  IsExactlyString<any | string>; // false
  IsExactlyString<unknown | string>; //  false
 * ````
 */
type IsExactlyString<T> = Equals<T, string>;
/**
 * @returns `true` if `T` is `boolean`, otherwise `false`.
 */
type IsBoolean<T> = IfExtends<T, boolean, true, false>;
/**
 * A numeric type iincludes `number` and `bigint`.
 * @returns `true` if `T` is a numeric type, otherwise `false`.
 */
type IsNumeric<T> = IfExtends<T, Numeric, true, false>;
/**
 * Represents a tuple.
 * @example
 * ````ts
 * Tuple<['a', 'b']>; // Result: ['a', 'b']
 * Tuple<string[]>; // Result: never
 */
type Tuple<T> = T extends readonly unknown[] ? number extends T['length'] ? never : T : never;
/**
 * Represents a tuple of size `N`, where `N` is a positive integer.
 * The tuple's length is exactly `N`, with each element of the tuple being of type `T`.
 *
 * @template T The type of the elements in the tuple.
 * @template N The desired length of the tuple.
 * @template Acc Accumulator type for recursive construction.
 *
 * @example
 * ```
 * SizedTuple<string, 3>; // Result: [string, string, string]
 * SizedTuple<number, 2>; // Result: [number, number]
 * SizedTuple<number, 0>; // Result: []
 * ```
 *
 * @see Tuple
 */
type SizedTuple<T, N extends Numeric, Acc extends T[] = []> = N extends PositiveInteger<infer M> ? Acc['length'] extends M ? Acc : SizedTuple<T, M, [T, ...Acc]> : never;
/**
 * Is a given type `T` an array?
 * @returns `true` if `T` it is, otherwise `false`.
 * @example
 * ```
 * IsArray<number[]>; // true
 * IsArray<string>; // false
 * ```
 */
type IsArray<T> = IfExtends<T, unknown[], true, false>;
/**
 * Represents a unique array type that filters out duplicate elements.
 * If a duplicate is encountered, it returns a tuple with an error message and the duplicate element.
 *
 * @template T The type of the elements in the array, which must be a readonly array.
 * @returns A readonly array of unique elements or a tuple indicating a duplicate.
 *
 * @example
 * ```
 * type Result1 = UniqueArray<[1, 2, 3, 1]>; // Result: ['Encountered duplicate element', 1]
 * type Result2 = UniqueArray<[1, 2, 3]>; // Result: [1, 2, 3]
 * type Result3 = UniqueArray<[]>; // Result: []
 * ```
 */
type UniqueArray<T extends readonly any[], Seen = never> = T extends readonly [infer Head, ...infer Tail] ? Head extends Seen ? ['Encountered duplicate element', Head] : readonly [Head, ...UniqueArray<Tail, Seen | Head>] : T;
/**
 * @returns `true` if `Arr` is an array that includes elements of type `T`, otherwise `false`.
 * An array of elements of type `T` is defined as `Arr` being a subtype of `T[]`.
 * @example
 * ```
 * IsArrayIncludeTypeof<Record<string, number>[], number> // false
 * IsArrayIncludeTypeof<string[], null | boolean> // false
 * ArrayIncludeTypeof<string[], string | boolean> // true
 * IsArrayIncludeTypeof<Record<string, number>[], Record<symbol, boolean>> // true,
 * ```
 */
type IsArrayIncludesTypeof<Arr, T> = IfExtends<Arr, T[], true, false>;
/**
 * Type utility that checks if a given type `T` is an `AnyFunction` (any function type).
 * @template T The type to check.
 * @returns `true` if `T` is an `AnyFunction`, otherwise `false`.
 * An `AnyFunction` is defined as a function type that accepts any arguments and returns any value.
 * @example
 * ```
 * IsAnyFunction<() => void>; // true (matches AnyFunction)
 * IsAnyFunction<(x: number) => string>; // true (matches AnyFunction)
 * IsAnyFunction<string>; // false (string is not a function type)
 * ```
 */
type IsAnyFunction<T> = IfExtends<T, AnyFunction, true, false>;
/**
 * Type utility that checks if a given type `T` is a `Function` (function type accepting `unknown` arguments and returning `unknown`).
 * @template T The type to check.
 * @returns `true` if `T` is a `Function`, otherwise `false`.
 * A `Function` is defined as a function type that accepts arguments of type `unknown` and returns a value of type `unknown`.
 * @example
 * ```
 * IsFunction<() => void>; // true (matches Function)
 * IsFunction<(x: number) => string>; // true (matches Function)
 * IsFunction<string>; // false (string is not a function type)
 * ```
 */
type IsFunction<T> = IfExtends<T, UnknownFunction, true, false>;
/**
 * Checks if a given type `T` qualifies as an object.
 * @returns `true` if it is, otherwise `false`.
 * An object in this context is defined as a non-null object (excluding functions and arrays).
 * @example
 * ```
  IsObject<object>; // true
  IsObject<{ name: string }>; // true
  IsObject<string>; // false
  IsObject<Function>; // true, yes, the built-in Function type is an interface with a bunch of methods, so yes it's an object.
  // if you want to use the function type use this:
  IsObject<UnknownFunction>; // false
  // or this
  IsObject<AnyFunction>; // false
  IsObject<any[]>; // false
  IsObject<null>; // false
 * ```
 */
type IsObject<T> = And<IfExtends<T, object, true, false>, And<Not<IsFunction<T>>, Not<IsArray<T>>>>;
/**
 * @returns `true` if `T` is `number`, otherwise `false`.
 */
type IsNumber<T> = IfExtends<T, number, true, false>;
/**
 * @returns `true` if `T` is exactly of type `number`, otherwise `false`.
 * @example
 * ````ts
  IsExactlyNumber<any | number>; // false
  IsExactlyNumber<unknown | number> // false
  IsExactlyNumber<number> // true
  IsExactlyNumber<87> // false
 * ````
 */
type IsExactlyNumber<T> = Equals<T, number>;
/**
 * @returns `true` if `T` is `bigint`, otherwise `false`.
 */
type IsBigInt<T> = IfExtends<T, bigint, true, false>;
/**
 * @returns `true` if `T` is exactly `bigint`, otherwise `false`.
 * @example
 * ````ts
  IsBigInt<unknown | bigint>; // false
  IsBigInt<symbol | Nullable>; // false
  IsBigInt<bigint>; // true
 * ````
 */
type IsExactlyBigInt<T> = Equals<T, bigint>;
/**
 * @returns `true` if `T` is `symbol`, otherwise `false`.
 */
type IsSymbol<T> = T extends symbol ? true : false;
/**
 * @returns `true` if `T` is exactly `symbol`, otherwise `false`.
 * @example
 * ````ts
  IsExactlySymbol<symbol>; // true
  IsExactlySymbol<any | symbol>; // false
  IsExactlySymbol<Integer<2>>; // false
 * ````
 */
type IsExactlySymbol<T> = Equals<T, symbol>;
/**
 * If ``T`` is exactly``any``, return ``true``, otherwise, return ``false``.
 * @example
 * ````ts
  IsExactlyAny<any | Nullable>; // true, once unsafe, always unsafe
  IsExactlyAny<Numeric | Nullable>; // false
  IsExactlyAny<unknown>; // false
  IsExactlyAny<any>, true
 * ````
 */
type IsExactlyAny<T> = Equals<T, any>;
/**
 * Checks if a given numeric value is in ]-∞,0[
 * @returns
 * true if it is, otherwise false
 */
type IsNegative<N extends Numeric> = StringifyPrimitive<N> extends `-${infer U}` ? true : false;
/**
 * Checks if a given numeric value is in [0,+∞[
 * @returns
 * true if it is, otherwise false
 */
type IsPositive<N extends Numeric> = N extends N ? Numeric extends N ? boolean : `${N}` extends `-${Numeric}` ? false : true : never;
/**
 * Check if a given numeric value is an integer
 * @returns
 * true if it is, else false
 */
type IsInteger<N extends Numeric> = number extends N ? false | true : N extends N ? `${N}` extends `${string}.${string}` ? false : true : never;
/**
 * Check if a given numeric value is an float
 * @returns
 * true if it is, else false
 */
type IsFloat<N extends Numeric> = number extends N ? false | true : N extends N ? `${N}` extends `${string}.${string}` ? true : false : never;
/**
 * @returns `true` if `T` is a `Newable`, otherwise `false`.
 */
type IsNewable<T> = IfExtends<T, Newable, true, false>;
/**
 * Conditional type: if the condition `C` is `true`, return `Do`, otherwise return `Else`.
 * @example
 * ````ts
   If<IsNever<never>, true, false>; // true
   If<Not<IsNever<never>>, true, false>; // false
 * ````
*/
type If<C extends boolean, Do, Else> = IfExtends<C, true, Do, Else>;
/**
 * Negates a boolean type `B`.
 * @example
   Not<true>; // false
   Not<false>; // true
*/
type Not<B extends boolean> = B extends true ? false : true;
/**
 * Logical AND between two boolean types `B1` and `B2`.
 * @example
   And<true, false>; // false
   And<true, true>; // true
*/
type And<B1 extends boolean, B2 extends boolean> = If<B1, If<B2, true, false>, false>;
/**
 * Logical OR between two boolean types `B1` and `B2`.
 * @example
   Or<true, false>; // true
   Or<false, false>; // false
*/
type Or<B1 extends boolean, B2 extends boolean> = If<B1, true, If<B2, true, false>>;
/**
 * Exclusive OR (XOR) between two boolean types `B1` and `B2`.
 * @example
   Xor<true, false>; // true
   Xor<true, true>; // false
*/
type Xor<B1 extends boolean, B2 extends boolean> = Or<And<B1, Not<B2>>, And<Not<B1>, B2>>;
/**
 * Logical NAND between two boolean types `B1` and `B2`.
 * @example
   Nand<true, false>; // true
   Nand<true, true>; // false
*/
type Nand<B1 extends boolean, B2 extends boolean> = Not<And<B1, B2>>;
/**
 * Represents the keys of a given  type `T`.
 * This  type alias `Keys<T>` is equivalent to `keyof T`,
 * which retrieves the union  type of keys (property names) of  type `T`.
 * @returns Union  type of keys (property names) of  type `T`.
 * @example
 *  type Person = {
 *   name: string;
 *   age: number;
 *   email: string;
 * };
 *
 *  type PersonKeys = Keys<Person>; => "name" | "age" | "email"
 */
type Keys<T> = keyof T;
/**
 * Represents the union  type of values of properties in a given  type `T`.
 * This  type alias `Vals<T>` retrieves the union  type of values corresponding
 * to the keys (property names) of  type `T`.
 * @example
 *  type Person = {
 *   name: string;
 *   age: number;
 *   email: string;
 * };
 *
 *  type PersonValues = Vals<Person>; => string | number
 */
type Vals<T> = T[Keys<T>];
/**
 * Represents a  type that can be either a single value of  type `T` or an array of values of  type `T`.
 * @example
 * type T1 = EitherOneOrMany<number>; 10; // Valid
 * type T2 = EitherOneOrMany<number>;  [20, 30]; // Also valid
 */
type EitherOneOrMany<T> = T | T[];
/**
 * Turns a given primitive value (except symbol) into its string representation
 * @example
 * ```ts
StringifyPrimitive<45> //  "45"
StringifyPrimitive<boolean> //  "false" | "true"
StringifyPrimitive<null> // "null"
StringifyPrimitive<undefined> // "undefined"
 * ```
 */
type StringifyPrimitive<P extends Exclude<Primitive, symbol>> = `${P}`;
/**
 * Turn a given string literal to a numeric
 * @example
 * ````ts`
 NumerifyString<'54'>; // 54
 NumerifyString<'699620.000000001'>; // 699620.000000001
 IsNegativeFloat<NumerifyString<'-699620.000000001'>>; // true
 * ````
 */
type NumerifyString<S extends string> = S extends `${infer N extends Numeric}` ? N : never;
/**
 * Check if a string starts with another string
 * @example
 * ```ts
 * type Result = StringStartsWith<'hello world', 'hello'>; // Result: true
 * ```
 */
type StringStartsWith<T extends string, U extends string> = IfExtends<T, `${U}${string}`, true, false>;
/**
 * Check if a string starts with a given prefix and ends with a given suffix
 * @example
 * ```ts
 * type Result = EnforcedString<'pk_123', 'pk_'>; // Result: 'pk_123'
 */
type EnforcedString<T extends string, Prefix extends string = '', Suffix extends string = ''> = StringStartsWith<T, Prefix> extends true ? StringEndsWith<T, Suffix> extends true ? T : never : never;
/**
 * Check if a string ends with another string
 * @example
 * ```ts
 * type Result = StringEndsWith<'hello world', 'world'>; // Result: true
 * ```
 */
type StringEndsWith<T extends string, U extends string> = IfExtends<T, `${string}${U}`, true, false>;
/**
 * Get the absolute value of a numeric N
 * @example
 * ```ts
 * Abs<-54>; // Result: 54
 * Abs<54>; // Result: 54
 * ```
 * @returns
 * |N|
 */
type Abs<N extends Numeric> = `${N}` extends `-${infer M extends Numeric}` ? M : N;
/**
 * Get the length of a given string
 * @example
 * ```ts
 * Strlen<'foo'>; // Result: 3
 * ```
 *
 * Can be used to create type constraints on string lengths:
 * ```ts
 * // Only allow strings of length 8-10 characters
 * type ValidPassword<T extends string> = Strlen<T> extends 8 | 9 | 10 ? T : never;
 *
 * // Function that only accepts valid password strings
 * function checkValidPassword<T extends string>(val: T & ValidPassword<T>) {
 *   console.log(val);
 * }
 *
 * // Works with string literals
 * const validPass = checkValidPassword('password123' as const); // OK
 * const invalidPass = checkValidPassword('short' as const); // Type error
 * ```
 */
type Strlen<S extends string, Arr extends any[] = EmptyArray> = S extends `${infer L}${infer R}` ? Strlen<R, [...Arr, L]> : Arr['length'];
/**
 * Check if two strings S1 and S2 have the same length
 * @returns
 * ``true`` if they do, else ``false``
 */
type EqualStrlen<S1 extends string, S2 extends string> = Equals<Strlen<S1>, Strlen<S2>>;
type EmptyArray = [];
/**
 * Conditional  type that checks if  type `T` extends  type `P`.
 * If `T` extends `P`, the  type resolves to `Do`; otherwise `Else`.
 * @example
 *  type Result1 = IfExtends<string, string | number, true, false>; // is true
 *  type Result2 = IfExtends<number, string | number, true, false>; // is true
 *  type Result3 = IfExtends<boolean, string | number, true, false>; // is false
 *
 *  type IsString<T> = IfExtends<T, string, true, false>;
 *  type IsNumber<T> = IfExtends<T, number, true, false>;
 *
 *  type TestString = IsString<string>; // is true
 *  type TestNumber = IsNumber<number>; // is true
 *  type TestBoolean = IsNumber<boolean>; // is false
 */
type IfExtends<T, P, Do, Else> = T extends P ? Do : Else;
/**
 * Conditional type that checks if type `T` is equal to type `P`.
 * If `T` is equal to `P`, the type resolves to `Do`, otherwise `Else`.
 * @example
 *  type Result1 = IfEquals<string, string, true, false>; // is true
 *  type Result2 = IfEquals<number, string, true, false>; // is false
 *  type Result3 = IfEquals<boolean, boolean, true, false>; // is true
 *
 *  type IsExactlyString<T> = IfEquals<T, string, true, false>;
 *  type IsExactlyNumber<T> = IfEquals<T, number, true, false>;
 *
 *  type TestString = IsExactlyString<string>; // is true
 *  type TestNumber = IsExactlyNumber<number>; // is false
 *  type TestBoolean = IsExactlyString<boolean>; // is false
 */
type IfEquals<T, P, Do, Else> = Equals<T, P> extends true ? Do : Else;
/**
 * Conditional  type that checks if two types `X` and `Y` are exactly equal.
 * If `X` is equal to `Y`, the  type resolves to `true`; otherwise `false`.
 * @example
 *  type Result1 = Equals<string, string>; // is true
 *  type Result2 = Equals<number, string>; // is false
 *  type Result3 = Equals<boolean | string, string | boolean>; // is true
 */
type Equals<X, Y> = (<T>() => T extends X ? true : false) extends <T>() => T extends Y ? true : false ? true : false;
/**
 A  type that excludes `null` and `undefined` from  type `T`.
 * @example
 Type Str = ExcludeNullable<string | null> //  string
 Type Str2 = ExcludeNullable<string | null | undefined> //  string
 Type Str3 = ExcludeNullable<string | undefined> //  string
 *
 */
type ExcludeNullable<T> = Exclude<T, Nullable>;
/**
 A  type that excludes `undefined` from  type `T`.
 * @example
 Type Str = ExcludeNullable<string | undefined> // Result:  string
 */
type ExcludeUndefined<T> = Exclude<T, undefined>;
/**
 * A  type that excludes `null` from  type `T`.
 * @example
 Type Str = ExcludeNullable<string | null> // Result:  string
 */
type ExcludeNull<T> = Exclude<T, null>;
/**
 * Get the literal names of keys that are methods in object type `T`
 * @example
 * ````ts
 Methods<{
      foo: () => void;
      bar: (a: any) => string;
      barBaz: string;
      bazBar: Numeric;
    }> // Result: 'foo' | 'bar'
 * ````
 */
type Methods<T extends object> = {
    [K in Keys<T>]-?: ExcludeNullable<T[K]> extends AnyFunction ? K : never;
}[Keys<T>];
/**
     * Get the literal names of keys that are propeties, basically anything that's not a method in object type `T`
     * @example
     * ````ts
     Properties<{
          barBaz: string;
          bazBar: Numeric;
          bar: () => number;
        }> // Result: 'barBaz' | 'bazBar'
     * ````
     */
type Properties<T extends object> = {
    [K in Keys<T>]-?: ExcludeNullable<T[K]> extends AnyFunction ? never : K;
}[Keys<T>];
/**
 * Evaluates whether one type `T` is assignable to another type `U`.
 * @returns `true` if `T` is assignable to `U`, `false` otherwise.
 *
 * @example
 * ```typescript
 * type A = { x: number };
 * type B = { x: number; y: string };
 * type C = { x: number; y?: string };
 *
 * type Check1 = Extends<A, B>; // false, A does not extend B
 * type Check2 = Extends<B, A>; // true, B extends A
 * type Check3 = Extends<C, B>; // true, C extends B
 * ```
 */
type Extends<T, U> = T extends never ? false : T extends U ? true : false;
/**
 * @hidden
 */
type _FlippableRecord = Record<string, string | number | boolean>;
/**
 * Constructs a new type that takes an object type `T` and returns a new object type where the keys of `T` become
 * the values and the values become the keys.
 *
 * @example
 * ```typescript
 * type Object1 = { name: 'John'; age: 30; city: 'New York' };
 * type Flipped1 = Flip<Object1>; // {'John': 'name', 30: 'age', 'New York': 'city'}
 *
 * type Object2 = { fruit: 'Apple'; color: 'Red'; price: 1.25 };
 * type Flipped2 = Flip<Object2>; // {'Apple': 'fruit', 'Red': 'color', 1.25: 'price'}
 *
 * type Object3 = { optionA: true; optionB: false };
 * type Flipped3 = Flip<Object3>; // {true: 'optionA', false: 'optionB'}
 * ```
 */
type Flip<T extends _FlippableRecord> = {
    [P in Keys<T> as StringifyPrimitive<T[P]>]: P;
};
/**
 * Constructs a new type by replacing keys of type `T` in object type `U` with corresponding keys from object type `Y`.
 * @template U The original object type.
 * @template T The type of keys to replace.
 * @template Y The object type containing replacement keys.
 *
 * @example
 * ```typescript
 * type Original = {
 *   bar: string;
 *   foo: number;
 *   fooBar: string;
 * };
 *
 * type Replacement = ReplaceKeys<Original, 'bar', { bar: number }>;
 *
 * // Result: { bar: number; foo: number; fooBar: string; }
 *
 * type AnotherReplacement = ReplaceKeys<Original, 'foo', { foo: boolean }>;
 *
 * // Result: { bar: string; foo: boolean; fooBar: string; }
 * ```
 */
type ReplaceKeys<U, T, Y> = {
    [K in Keys<U>]: IfExtends<K, T, K extends Keys<Y> ? Y[K] : never, U[K]>;
};
/**
 * A  type that recursively mutates all the proprties within a given object  type `T`.
 *
 * @example
 * ````ts
type Actual = {
  readonly a: () => 1;
  readonly x: string;
  readonly s: {
    readonly q: Nullable;
    readonly s: {
      readonly i: {
        readonly x: {
          readonly o: Maybe<Primitive>;
          readonly n: Falsy;
        };
        readonly e: 'foo';
      };
    };
  };
};

type Expected = {
  a: () => 1;
  x: string;
  s: {
    q: Nullable;
    s: {
      i: {
        x: {
          o: Maybe<Primitive>;
          n: Falsy;
        };
        e: 'foo';
      };
    };
  };
};
type T = DeepMutable<Actual>; // T Results in: Expected
 * ````
 */
type DeepMutable<T> = T extends UnknownFunction ? T : {
    -readonly [K in Keys<T>]: T[K] extends unknown ? DeepMutable<T[K]> : T[K];
};
/**
 * Checks if all the nested properties of a given object T are actually mutable.
 */
type IsDeepMutable<T> = T extends DeepMutable<T> ? true : false;
/**
 * Checks if all the nested properties of a given object T are actually immutable.
 */
type IsDeepImmutable<T> = T extends DeepImmutable<T> ? true : false;
/**
 * Check if all the properties of a given object (nested) are required
 * @returns
 * `true` if all the properties are, otherwise `false`
 */
type IsDeepRequired<T> = IfExtends<T, DeepRequired<T>, true, false>;
/**
 * Check if all the properties of a given object (nested) are non required
 * @returns
 * `true` if all the properties are, otherwise `false`
 */
type IsDeepNotRequired<T> = IfExtends<T, DeepNotRequired<T>, true, false>;
/**
 * A  type that recursively turns the proprties within a given object  type `T` immutable.
 * @example
 * ````ts
type Actual = {
  a: () => 1;
  x: string;
  s: {
    q: Nullable;
    s: {
      i: {
        x: {
          o: Maybe<Primitive>;
          n: Falsy;
        };
        e: 'foo';
      };
    };
  };
};

type Expected = {
  readonly a: () => 1;
  readonly x: string;
  readonly s: {
    readonly q: Nullable;
    readonly s: {
      readonly i: {
        readonly x: {
          readonly o: Maybe<Primitive>;
          readonly n: Falsy;
        };
        readonly e: 'foo';
      };
    };
  };
};
type T = DeepImmutable<Actual>; // T Results in: Expected
 * ````
 * */
type DeepImmutable<T> = T extends UnknownFunction ? T : {
    readonly [K in Keys<T>]: T[K] extends unknown ? DeepImmutable<T[K]> : T[K];
};
declare const __s: unique symbol;
/**
 * This type represents a new unique type derived from an existing base type.
 * It defines a mechanism similar to Python's [`NewType`](https://docs.python.org/3/library/typing.html#newtype).
 * In TypeScript world it's refered to as 'Type Branding'.
 *
 * @template N The unique identifier for the new type.
 * @template T The base type of the new type.
 *
 * @example
 * type FooID = NewType<'FooID', string>;
 * type BarID = NewType<'BarID', string>;
 *
 * const fooId: FooID = 'foo123' as FooID;
 * const barId: BarID = 'bar456' as BarID;
 *
 * // Here's a potential bug:
 * const buggyFooBar = (foo: string, bar: string) => {};
 * buggyFooBar('bar456', 'foo123'); // this works but it's an undetected bug.
 *
 * // Bug mitigation:
 * const safeFooBar = (foo: FooID, bar: BarID) => {};
 * safeFooBar('bar456', 'foo123'); // TypeScript error: Argument of type 'string' is not assignable to parameter of type 'FooID'.
 */
type NewType<N, T> = T & {
    /**
     * Property `__s` is not intended for direct access nor modification.
     * @internal
     */ [__s]: N;
};
/**
 * Type that recursively omits specified nested properties from an object type.
 * @template T The input object type.
 * @template P A **string** literal representing the path of properties to omit (e.g., 'person.name.value').
 * @example
 * ```typescript
 * type T =
 *   a: {
 *     b: string;
 *     b2: {
 *       c: {
 *         d: number;
 *       };
 *     };
 *   };
 * }
 *
 * DeepOmit<T, 'a.b2.c'> // Results in: { a: { b: string; b2: {} } }
 * ```
 */
type DeepOmit<T, P extends string> = P extends `${infer K}.${infer R}` ? {
    [KT in Keys<T>]: KT extends K ? DeepOmit<T[KT], R> : T[KT];
} : Omit<T, P>;
/**
 * As the name implies, it turns a union into an intersection
 * @example
  type T = NewType<'T', string>;
  type Result = UnionToIntersection<
      (() => 'foo') | ((baz: 88) => Optional<NewType<'T', string>>)
    >
    // Result: (() => 'foo') & ((baz: 88) => Optional<T>)

    type Result2 = UnionToIntersection<
      IsFalsy<0> | IsDeepImmutable<{ a: string; readonly b: string }>
    >
    // Result 2: IsFalsy<0> & IsDeepImmutable<{ a: string; readonly b: string }> => true & true => evaluates to true
 *
 */
type UnionToIntersection<U> = (U extends unknown ? (arg: U) => unknown : never) extends (arg: infer I) => void ? I : never;
/**
 * @hidden
 */
type _FindPrimitive<T> = T extends string ? string : T extends symbol ? symbol : T extends boolean ? boolean : T extends null ? null : T extends number ? number : T extends bigint ? bigint : T extends undefined ? undefined : never;
/**
* @example
* Recursively transforms an object type `T` into a type where all properties
* are replaced with their corresponding primitive types.
* ````ts
type Actual = {
  a: 'a';
  b: 85;
  c: true;
  d: {
    e: 'xxxxxxxxxxx';
    f: 'eeeeeeeeeeeeeeeeee';
    g: {
      h: 1000000000000000;
      i: undefined;
      j: null;
    };
  };
};
type Expected = {
  a: string;
  b: number;
  c: boolean;
  d: {
    e: string;
    f: string;
    g: {
      h: number;
      i: undefined;
      j: null;
    };
  };
};
type Result = DeepToPrimitive<Actual>; // Expected
* ````
*/
type DeepToPrimitive<T> = {
    [K in Keys<T>]: T[K] extends object ? DeepToPrimitive<T[K]> : _FindPrimitive<T[K]>;
};
/**
 * @hidden
 */
type __Merge<T, S> = {
    [K in Keys<T> | Keys<S>]: K extends Keys<S> ? S[K] : T[K & Keys<T>];
};
/**
 * Copies all enumerable own properties from one target object
 * to a source array of objects.
 * @example
 * ````ts
 type T = Assign<{ a: 'd'; d: 'd' }, [{ a: 'a' }, { b: 'b' }, { c: 'c' }]>
 // Result:
 {
      a: 'a';
      b: 'b';
      c: 'c';
      d: 'd';
    }
 * ````
 */
type Assign<T extends Record<string, unknown>, Arr extends unknown[]> = Arr extends [infer S, ...infer E] ? Assign<S extends object ? __Merge<T, S> : T, E> : T;
/**
 * Get the common keys between two objects, if a key is found to be shared between both,
 * then the type of that key will take the first object's key type
 * @returns
 * An object that consist of what's common in both, else never
 * @example
 * ````ts
 CommonKeys<
      { d: 'first objects d'; x: 'also first objects x' },
      { d: 'd'; p: { b: 'b' }; x: { c: 'c' } }
    >
    // Results in { d: 'first objects d'; x: 'also first objects x' }
 * ````
 */
type PickCommonKeys<T extends Record<string, unknown>, U extends Record<string, unknown>> = Pick<T, Extract<Keys<T>, Keys<U>> & Extract<Keys<U>, Keys<T>>>;
/**
 * Omit the common keys between the the two objects,
 * @returns
 * An object that consist of what's unique in both, else never
 * @example
 * ````ts
 OmitCommonKeys<{ d: { d: 'a' }; p: { b: 'b' }; x: { c: 'c' } }, { d: 'd' }>
 // Result:
 {
      p: {
        b: 'b';
      };
      x: {
        c: 'c';
      };
    }

 OmitCommonKeys<
      { d: 'd'; k: 'k' },
      { d: 'd'; p: { b: 'b' }; x: { c: 'c' } }
    >
  // Result:
  { k: 'k' }
 * ````
 */
type OmitCommonKeys<T extends Record<string, unknown>, U extends Record<string, unknown>> = Pick<T, Exclude<Keys<T>, Keys<U>>>;
/**
 * Deeply pick properties from a nested object type.
 * @template T The target object.
 * @template P A dot-separated string literal representing the path of properties to pick.
 * @example
 * type T = {
  one: string;
  two: {
    a: boolean;
    b: null;
    c: 'c' | 'C';
  };
  thee: number;
};
 * DeepPick<T, 'two.c'> // Results in:
{
    two: {
      c: 'c' | 'C';
    };
  }
 *
 */
type DeepPick<T extends Record<string, any>, // need to use `any` here for `T[K1]` inference
P extends string> = UnionToIntersection<P extends `${infer K}.${infer R}` ? {
    [K1 in K]: DeepPick<T[K1], R>;
} : P extends Keys<T> ? Pick<T, P> : never>;
/**
 * Retrieves the keys that are mutable from an object of  type T.
 * Basically keys that are not marked with the `readonly` modifier
 * @example
 * ```typescript
 *  type ExampleType = {
 *   a: number;
 *   readonly b: string;
 *   c: {
 *     a: string;
 *     d: { readonly x: Nullable; v: Maybe<Newable> };
 *   };
 * };
 *
 *  type MutableKeysOfExampleType = MutableKeys<ExampleType>;
 * // Result: 'a' | 'c'
 * ```
 */
type MutableKeys<T> = {
    [P in Keys<T>]: Equals<Pick<T, P>, Readonly<Pick<T, P>>> extends true ? never : P;
}[Keys<T>];
/**
 * Retrieves the keys that are immutable (readonly) from an object of  type T.
 * @example
 * ```typescript
 *  type ExampleType = {
 *   a: number;
 *   readonly b: string;
 *   c: {
 *     a: string;
 *     d: { readonly x: Nullable; v: Maybe<Newable> };
 *   };
 * };
 *
 *  type ImmutableKeysOfExampleType = ImmutableKeys<ExampleType>;
 * // Result: 'b'
 * ```
 */
type ImmutableKeys<T> = {
    [P in Keys<T>]: Equals<Pick<T, P>, Readonly<Pick<T, P>>> extends true ? P : never;
}[Keys<T>];
/**
 * Determines if two types match.
 * @template T1 The first  type to compare.
 * @template T2 The second  type to compare.
 * @template Expected A boolean literal indicating whether `T1` should match `T2`.
 * If you expect the types to match, set this to ``true``; if not, set it to false.
 * This utility will return a boolean that is ``true`` if your expectation was correct, otherwise false.
 * @example
```typescript
type ResultType = TestType<Type1, Type2, true>;
```
``TestType`` accepts three arguments: the types you're comparing (``Type1`` and ``Type2``) and a boolean (``true`` if you expected them to match, ``false`` otherwise). The resulting type will tell if your expectation is correct, ``true`` if it is, else ``false``.

You can use it however you want, maybe to test a type on the go, or,
test using a testing framework. Here's an example with [`vitest`](https://vitest.dev)

````ts
import type { Abs, TestType } from 'ts-roids';
import { test, expect , expectTypeOf} from 'vitest';

test('|-54| should be 54',() => {
  type ShouldPass = true;
  expectTypeOf<TestType<Abs<-54>, 54, true>>().toEqualTypeOf<ShouldPass>();
});
 * ````
 * */
type TestType<T1, T2, Expected extends boolean> = Equals<Equals<T1, T2>, Expected>;
/**
 * Infers a mapping from values to their corresponding keys within a given object type `T`.
 * The resulting type provides a reverse lookup, which allows to to retrieve the keys based on specific values.
 * @remarks
 * > This type only works with simple object types without nested structures or complex types.
 * It may not behave as expected with objects containing nested properties, union types, intersections, or other
 * advanced constructs.
 *
 * For example, given a simple object type `T`:
 *
 * ```typescript
 * type SimpleObjectType = {
 *   name: 'Zee';
 *   age: 29;
 *   city: 'Zion';
 * };
 *
 * type T =  KeysToValues<SimpleObjectType> // results in:
 *
 * {
 *   Zee : 'name';
 *   29: 'age';
 *   'Zion': 'city';
 * }
 * ```
 */
type KeysToValues<T extends Record<Keys<T>, Keys<any>>> = {
    [K in T[Keys<T>]]: {
        [K1 in Keys<T>]: T[K1] extends K ? K1 : never;
    }[Keys<T>];
};
/**
 * `FilterBy<T, P>` filters keys from the object type `T` based on a specified predicate `P`.
 *
 * @remark
 * > This type performs a shallow filtering of keys within `T` and does not check deeply nested types
 * or complex structures within the object type.
 *
 * > It does not return the key as a whole object, it just returns the key itself
 * @example
 *
 * ```typescript
 * type T = {
 *   a: () => 1;
 *   x: string;
 *   s: {
 *     q: Nullable;
 *     s: {
 *       i: {
 *         x: {
 *           o: boolean;
 *           n: Falsy;
 *         };
 *         e: 'foo';
 *       };
 *     };
 *   };
 * };
 *
 * ```
 * ```typescript
 * type _ = FilterBy<T, 'a'>
 * ```
 * Results in the type `'a'`, which includes only the key `'a'` from `T`.
 * ```typescript
 * type _ = FilterBy<T, Falsy>
 * ```
 * Results in the type `never`, indicating that no keys in `T` match the type `Falsy`.
 *
 * ```typescript
 * type _ = FilterBy<T, string>
 * ```
 * Results in the type `'a' | 'x' | 's'`, which includes all top-level keys of `T`
 * that are of type `string`. It did not pick up on 'e' as it is nested down.
 */
type FilterBy<T, P> = {
    [K in Keys<T>]: K extends P ? K : never;
}[Keys<T>];
/**
 * Get a set of properties from `T` whose type are not assignable to `P`.
 * @example
 * ````ts
 * type T = {
 *  foo: string,
 *  bar: bigint | boolean,
 *  baz: number,
 * }
 * OmitByType<T,true>; // Result: T
 * OmitByType<T,number>; // Result: { foo: string, bar: bigint | boolean }
 * ````
 */
type OmitByType<T, P> = {
    [K in Keys<T> as T[K] extends P ? never : K]: T[K];
};
/**
 * Get a set of properties from `T` whose type exactly matches `P`.
 * @example
 * ````ts
type deep = {
        isActive: boolean;
        count?: number;
        description: string | null;
        details: {
          id: bigint;
          name: string;
          nested: {
            title: string;
            subtitle: string;
            moreDetails: {
              numberId: bigint;
            };
          };
        };
        additionalInfo: string | boolean;
      }
type A = OmitExactlyByTypeDeep<deep, bigint>
// A results in:
 {
      isActive: boolean;
      count?: number;
      description: string | null;
      details: {
        name: string;
        nested: {
          title: string;
          subtitle: string;
          moreDetails: EmptyObject;
        };
      };
      additionalInfo: string | boolean;
    }
 * ````
 */
type OmitExactlyByTypeDeep<T, P> = {
    [K in Keys<T> as IfEquals<T[K], P, never, K>]: OmitExactlyByTypeDeep<T[K], P>;
};
/**
 * From ``T``, pick a set of properties whose type are assignable to ``P``.
 * @example
 * ````ts
 * type T = {
 *  foo: string,
 *  bar: bigint | boolean,
 *  baz: number,
 * }
 * PickByType<T,true>; // Result: {}
 * PickByType<T,number>; // Result: { baz: number }
 * ````
 */
type PickByType<T, P> = {
    [K in Keys<T> as T[K] extends P ? K : never]: T[K];
};
/**
 * From ``T``, pick a set of properties whose type excatly matches ``P``.
 * @example
 * ````ts
type OneLevelDeep = {
  foo: boolean;
  bar?: Numeric;
  baz: Nullable;
  fooBaz: bigint;
  bazFoo: string | boolean;
  seven: 7;
  aNum: number;
};
  type A = PickExactlyByType<OneLevelDeep, bigint>,
  // A results in:
    {
      fooBaz: bigint;
    },
  // Notice how it does not pick up seven
 type B = PickExactlyByType<OneLevelDeep, number>,
    {
      aNum: number;
    }
 * ````
 */
type PickExactlyByType<T, P> = {
    [K in Keys<T> as If<Equals<T[K], P>, K, never>]: T[K];
};
/**
 * Extracts keys from a type `T` that represent required properties.
 * Properties that are not marked with `?`.
 * @example
 * ```ts
 * type T = RequiredKeys<{ a: number; b?: string }> // Result:  'a'
 * ```
 */
type RequiredKeys<T> = {
    [K in Keys<T>]-?: IfExtends<EmptyObject, Pick<T, K>, never, K>;
}[Keys<T>];
/**
 * Why not call it ``OptionalKeys``?
 * ``Optional<T>`` in this library represents a type ``T`` that can be either ``T`` or ``null``. So creating
 * ``OptionalKeys`` type would entail removing any type that can be null, which is not the intention here.
 *
 * ``NonRequiredKeys<T>`` simply removes non required keys, as in any property of an object that is
 * marked with `?` operator
 * @example
 * ```ts
 * type T = NonRequiredKeys<{ a: number; b?: string }> // Result:  'b'
 * ```
 */
type NonRequiredKeys<T> = Exclude<Keys<T>, RequiredKeys<T>>;
/**
 * Make all object properties required
 * @example
 * ```ts
type Expected = {
  a: () => 1;
  x: string;
  s: {
    q: Nullable;
    s: {
      i: {
        x: {
          o: Maybe<Primitive>;
          n: Falsy;
        };
        e: 'foo';
      };
    };
  };
};

type Actual = {
  a?: () => 1;
  x?: string;
  s?: {
    q?: Nullable;
    s?: {
      i?: {
        x?: {
          o?: Maybe<Primitive>;
          n?: Falsy;
        };
        e?: 'foo';
      };
    };
  };
};
type T = DeepRequired<Actual>; // Result: Expected
 * ```
 */
type DeepRequired<T> = T extends UnknownFunction ? T : {
    [K in Keys<T>]-?: IfExtends<T[K], unknown, DeepRequired<T[K]>, T[K]>;
};
/**
 * Why not call it ``DeepOptional``?
 * ``Optional<T>`` in this library `Optional` represents a type ``T`` that can be either ``T`` or ``null``. So creating
 * ``DeepOptional`` type would entail adding null to every property, which is not the intention here.
 *
 * ``DeepNotRequired<T>`` turns all required keys in a given object (nested) to non required one.
 * non required as in: marked with `?` operator
 * @example
 * ```ts
type Actual = {
  a: () => 1;
  x: string;
  s: {
    q: Nullable;
    s: {
      i: {
        x: {
          o: Maybe<Primitive>;
          n: Falsy;
        };
        e: 'foo';
      };
    };
  };
};

type Expected = {
  a?: () => 1;
  x?: string;
  s?: {
    q?: Nullable;
    s?: {
      i?: {
        x?: {
          o?: Maybe<Primitive>;
          n?: Falsy;
        };
        e?: 'foo';
      };
    };
  };
};
type T = DeepNotRequired<Actual>; // Result: Expected
 * ```
 */
type DeepNotRequired<T> = T extends UnknownFunction ? T : {
    [K in Keys<T>]+?: IfExtends<T[K], unknown, DeepNotRequired<T[K]>, T[K]>;
};
/**
 * `NotIncluded` is a utility type that represents a value that should not be included
 * in the final type. It is primarily used within the `Prune` type to exclude certain
 * properties from the resulting object type.
 *
 * @remarks
 * The `NotIncluded` type is typically used in conditional types to exclude specific
 * branches of the type structure. When a condition matches, `NotIncluded` is applied
 * to those properties that should be omitted from the final type structure.
 *
 * @example
 * ```ts
 * type MyType = IfEquals<'foo', 'bar', string, NotIncluded>; // Result: NotIncluded
 * ```
 *
 * In the context of the `Prune` type, `NotIncluded` helps in filtering out properties
 * from deeply nested structures where certain conditions do not hold.
 */
type NotIncluded = NewType<'NotIncluded', string>;
/**
 * `Prune<T, N = NotIncluded>` is a utility type that recursively removes properties of
 * type `N` (defaulting to `NotIncluded`) from the object type `T`. Useful
 * for filtering out unwanted or excluded properties in complex, deeply nested object
 * structures, where  you need to clean up or transform types where certain properties should be excluded based
 * on specific generic type conditions.
 * @example
 * Consider the following example where `Prune` is used to exclude properties marked as `NotIncluded`:
 * ```ts
 * type OrderData = Prune<
    UserOrderDetails<
      OrderStatus.DELIVERED,
      UserActionType.PLACE_ORDER,
      ProductType.PHYSICAL,
      PaymentMethod.PAYPAL
    >
  >;
 * ```
 * Where `UserOrderDetails` is defined as:
 * ```ts

export enum OrderStatus {
  PENDING = 'PENDING',
  SHIPPED = 'SHIPPED',
  DELIVERED = 'DELIVERED',
  CANCELLED = 'CANCELLED',
  RETURNED = 'RETURNED',
}

export enum PaymentMethod {
  CREDIT_CARD = 'CREDIT_CARD',
  PAYPAL = 'PAYPAL',
  BANK_TRANSFER = 'BANK_TRANSFER',
  CASH_ON_DELIVERY = 'CASH_ON_DELIVERY',
  CREDITS = 'CREDITS',
}

export enum UserActionType {
  PLACE_ORDER = 'PLACE_ORDER',
  CANCEL_ORDER = 'CANCEL_ORDER',
  RETURN_ORDER = 'RETURN_ORDER',
  RATE_PRODUCT = 'RATE_PRODUCT',
  WRITE_REVIEW = 'WRITE_REVIEW',
}

export enum ProductType {
  DIGITAL = 'DIGITAL',
  PHYSICAL = 'PHYSICAL',
}

interface ShippingDetails {
  address: string;
  city: string;
  postalCode: string;
  country: string;
  deliveryDate: Maybe<string>;
}

type ProductPricing<T extends ProductType> = {
  basePrice: number;
  discount: number;
  finalPrice: number;
  inCountryDiscount: IfEquals<T, ProductType.PHYSICAL, number, NotIncluded>;
};

type ProductDetails<T extends ProductType> = {
  type: T;
  productId: string;
  productName: string;
  quantity: number;
  pricing: ProductPricing<T>;
  physicalDescription: IfEquals<
    T,
    ProductType.DIGITAL,
    {
      color: string;
      size: string;
    },
    NotIncluded
  >;
};

type PaymentBreakdown = {
  baseAmount: number;
  tax: number;
  discount: number;
  finalAmount: number;
};

interface PaymentDetails<PM extends PaymentMethod> {
  method: PM;
  transactionId: Maybe<string>;
  amountPaid: number;
  breakdown: IfEquals<PM, PaymentMethod.CREDITS, string, PaymentBreakdown>;
}

type UserOrderDetails<
  OS extends OrderStatus,
  UAT extends UserActionType,
  PT extends ProductType,
  PM extends PaymentMethod,
> = {
  orderId: string;
  userId: string;
  products: ProductDetails<PT>[];
  orderStatus: OS;
  shipping: IfEquals<
    PT,
    ProductType.PHYSICAL,
    {
      details: IfEquals<
        OS,
        OrderStatus.SHIPPED | OrderStatus.DELIVERED,
        ShippingDetails,
        NotIncluded
      >;
      deliveredOn: IfEquals<OS, OrderStatus.DELIVERED, Date, NotIncluded>;
      returnedOn: IfEquals<OS, OrderStatus.RETURNED, Date, NotIncluded>;
    },
    NotIncluded
  >;
  payment: PaymentDetails<PM>;
  actions: {
    type: UAT;
    timestamp: number;
    metadata: IfEquals<
      UAT,
      | UserActionType.PLACE_ORDER
      | UserActionType.CANCEL_ORDER
      | UserActionType.RETURN_ORDER,
      {
        ipAddress: string;
        deviceType: string;
      },
      NotIncluded
    >;
  }[];
};
 * ```
Any property marked as `NotIncluded` will be excluded from the resulting `OrderData` type, not as `undefined` or `null`, but completely excluded as if it never existed on the type

 * ```ts
  const testOrderData: OrderData = {
    orderStatus: OrderStatus.DELIVERED,
    actions: [
      {
        timestamp: 1663725600000,
        // Type 'UserActionType.RATE_PRODUCT' is not assignable to type 'UserActionType.PLACE_ORDER'.ts(2322)
        type: UserActionType.PLACE_ORDER,
        // Object literal may only specify known properties, and 'metadata' does not exist in type 'OmitExactlyByTypeDeep<{ type: UserActionType.PLACE_ORDER; timestamp: number; metadata: NotIncluded; }, NotIncluded>'.ts(2353)
        // metadata: {
        //   ipAddress: '127.0.0.1',
        //   deviceType: 'desktop',
        // },
      },
    ],
    orderId: '123',
    userId: 'abc',
    products: [
      {
        // Type 'ProdcutType.DIGITAL' is not assignable to type 'ProdcutType.PHYSICAL'.ts(2322)
        type: ProductType.PHYSICAL,
        productId: 'abc',
        productName: 'Test Product',
        quantity: 1,
        pricing: {
          basePrice: 10,
          discount: 0,
          finalPrice: 10,
          // If the product type is digital, the 'physicalDescription' property should be omitted
          // Object literal may only specify known properties, and 'inCountryDiscount' does not exist in type 'OmitExactlyByTypeDeep<ProductPricing<ProductType.DIGITAL>, NotIncluded>'.ts(2353)
          // physicalDescription: {
          //   color: 'Red',
          //   size: 'Large',
          // },
          inCountryDiscount: 87,
        },
      },
    ],
    payment: {
      amountPaid: 10,
      // If the PaymentMethod is CREDITS, the 'breakdown' property should be a string, no Breakdown object should exist
      // Type '{ baseAmount: number; tax: number; discount: number; finalAmount: number; }' is not assignable to type 'string'.
      breakdown: {
        baseAmount: 10,
        tax: 2,
        discount: 0,
        finalAmount: 12,
      },
      // Type 'PaymentMethod.BANK_TRANSFER' is not assignable to type 'PaymentMethod.PAYPAL'.ts(2322)
      // method: PaymentMethod.BANK_TRANSFER,
      method: PaymentMethod.PAYPAL,
      transactionId: '1234567890',
    },
    shipping: {
      deliveredOn: new Date(),
    },
  };
 * ```
 *
 * In this example, `Prune`  removes all properties within `UserOrderDetails`
 * that are marked with `NotIncluded`, resulting in a cleaned-up type structure.
 */
type Prune<T, N = NotIncluded> = OmitExactlyByTypeDeep<T, N>;
/**
 * `PartialExcept<T, K extends keyof T>` is a utility type that makes all properties of `T` optional
 * except for the properties specified in `K`, which are required. This is useful for scenarios
 * where you want to enforce that certain fields must be present while allowing others to be omitted.
 *
 * @template T - The original type from which to derive the new type.
 * @template K - A subset of keys from `T` that should remain required in the resulting type.
 *
 * @example
 * ```ts
 * type User = {
 *   id: number;
 *   name: string;
 *   email: string;
 * };
 *
 * type UserUpdate = PartialExcept<User, 'email'>; // Result: { id?: number; name?: string; email: string; }
 * ```
 */
type PartialExcept<T, K extends keyof T> = {
    [P in K]: T[P];
} & Partial<Omit<T, K>>;
/**
 * `KeysOfUnion` extracts the union of keys from a given union of object types.
 * This is useful in scenarios where you need to access all possible keys across
 * unioned object types within conditional or mapped types.
 *
 * @template T - The union of object types to extract keys from.
 *
 * @example
 * ```ts
 * type UnionKeys = KeysOfUnion<{ a: string } | { b: number }>; // Result: 'a' | 'b'
 * ```
 */
type KeysOfUnion<T> = T extends T ? keyof T : never;
/**
 * `Simplify<T>` flattens the structure of a given type by resolving intersections
 * and reducing redundant wrapping, making complex types easier to work with.
 * This type is particularly helpful for deeply nested mapped types, where
 * readability and simplicity of the resulting type is crucial.
 *
 * @template T - The type to simplify.
 *
 * @example
 * ```ts
 * type Flattened = Simplify<{ a: string } & { b: number }>; // Result: { a: string; b: number }
 * ```
 */
type Simplify<T> = {
    [KeyType in Keys<T>]: T[KeyType];
} & EmptyObject;
/**
 * `ExclusiveUnion<T>` creates a union type where each member has its own properties as required,
 * while properties from other members of the union are made optional and set to `undefined`.
 * This is useful for cases where different configurations or variants in a union require only their specific fields.
 *
 * @template T - The union of object types for which partially optionalized variants should be created.
 * @template AllKeys - The union of all possible keys across the union's types, derived from `KeysOfUnion`.
 *
 * @example
 * ```ts
 * type Config = ExclusiveUnion<
 *   | { dbConnectionString: string; maxConnections: number }
 *   | { apiEndpoint: string; apiKey: string }
 *   | { storageBucket: string; accessKeyId: string; secretAccessKey: string }
 * >;
 *
 * // Example usage:
 * function configureService(config: Config) {
 *   if (config.dbConnectionString) {
 *     console.log(`Configuring database with connection string ${config.dbConnectionString}`);
 *   } else if (config.apiEndpoint) {
 *     console.log(`Configuring API with endpoint ${config.apiEndpoint}`);
 *   } else if (config.storageBucket && config.accessKeyId && config.secretAccessKey) {
 *     console.log(`Configuring storage bucket ${config.storageBucket}`);
 *   } else {
 *     console.log('Invalid configuration');
 *   }
 * }
 *
 * configureService({ dbConnectionString: 'postgres://...', maxConnections: 100 });
 * configureService({ apiEndpoint: 'https://api.example.com', apiKey: '1234' });
 * configureService({ storageBucket: 'my-bucket', accessKeyId: 'AKIA...', secretAccessKey: 'abcd' });
 * ```
 */
type ExclusiveUnion<T extends object, AllKeys extends KeysOfUnion<T> = KeysOfUnion<T>> = Simplify<T extends unknown ? T & Partial<Record<Exclude<AllKeys, Keys<T>>, undefined>> : never>;
type LastOf<T> = UnionToIntersection<T extends any ? () => T : never> extends () => infer R ? R : never;
/**
 * `UnionToTuple<T>` converts a union type `T` into a tuple type.
 * This type is useful for scenarios where you need to work with the individual members of a union as an ordered list.
 *
 * @template T - The union type to convert into a tuple.
 * @template L - The last member of the union, used for recursive extraction.
 * @template N - A boolean that checks if the union is empty.
 *
 * @example
 * type TestUnion = 'a' | 'b' | 'c';
 * type ResultTuple = UnionToTuple<TestUnion>; // Result: ['a', 'b', 'c']
 */
type UnionToTuple<T, L = LastOf<T>, N = [T] extends [never] ? true : false> = N extends true ? [] : [...UnionToTuple<Exclude<T, L>>, L];
/**
 * Capitalizes the first character of a string literal type while preserving the rest.
 * This is particularly useful when you need to transform string literal unions into
 * their capitalized counterparts.
 *
 * @template T The string literal type to capitalize
 *
 * @example
 * ```ts
 * type Category = "software" | "health" | "philosophy";
 * type Result = CapitalizeFirst<Category>; // "Software" | "Health" | "Philosophy"
 *
 * type Single = CapitalizeFirst<"hello">; // "Hello"
 * ```
 */
type CapitalizeFirst<T extends string> = T extends `${infer First}${infer Rest}` ? `${Capitalize<First>}${Rest}` : T;
/**
 * Represents a range of positive integers from N to M (inclusive).
 * Both bounds must be positive integers.
 *
 * @template N Lower bound (must be positive integer)
 * @template M Upper bound (must be positive integer)
 *
 * @example
 * ```typescript
 * // Pagination example with a maximum of 100 items per page
 * interface PaginationParams {
 *   page: number;
 *   itemsPerPage: PositiveRange<1, 100>;
 * }
 *
 * async function fetchUsers({ page, itemsPerPage }: PaginationParams) {
 *   const offset = (page - 1) * itemsPerPage;
 *   return await db.users.findMany({
 *     skip: offset,
 *     take: itemsPerPage,
 *   });
 * }
 *
 * // Valid usage:
 * fetchUsers({ page: 1, itemsPerPage: 50 });  // ✅ OK
 *
 * // Type errors:
 * fetchUsers({ page: 1, itemsPerPage: 200 }); // ❌ Error: 200 exceeds maximum of 100
 * fetchUsers({ page: 1, itemsPerPage: 0 });   // ❌ Error: 0 is not in range
 * ```
 */
type PositiveRange<N extends number, M extends number> = [
    IsPositiveInteger<N>,
    IsPositiveInteger<M>
] extends [true, true] ? N extends M ? N : M extends N ? M : number extends N | M ? number : _BuildRange<N, M, []> : never;
/**
 * @hidden
 * @Internal helper to build range union recursively
 */
type _BuildRange<N extends number, M extends number, Acc extends number[], Current extends number = N> = Current extends M ? Current | Acc[number] : _BuildRange<N, M, [...Acc, Current], AddOne<Current>>;
/**
 * @hidden
 * @internal
 */
type AddOne<N extends number> = N extends keyof NumberMap ? NumberMap[N] : never;

/**
 * @hidden
 */
declare class FinalTypeError extends TypeError {
}
/**
 * Marks a class as final, preventing inheritance from this class.
 * When applied, any attempt to extend this class will result in a TypeError at runtime.
 * @remarks
 * This decorator does not prevent instantiation of the final class itself.
 * @example
 * ```ts
 * @Final
 * class Foo<T> {
 *   foo: T;
 *   bar: string;
 *
 *   constructor(foo: T) {
 *     this.foo = foo;
 *     this.bar = 'bar';
 *   }
 *
 *   someFoo(): T {
 *     return this.foo;
 *   }
 * }
 *
 * // No problem with instantiation
 * const foo = new Foo<string>('foo');

 * // The line below will cause a TypeError: Cannot inherit from the final class Foo
 * const sub = new SubFoo('subFoo');
 * ```
 * @see {@link https://github.com/microsoft/TypeScript/issues/1534| Issue #1}
 * @see {@link https://github.com/microsoft/TypeScript/issues/8306| Issue #2}
 * @see {@link https://github.com/microsoft/TypeScript/issues/50532| Issue #3}
 */
declare const Final: <CST extends Newable>(cst: CST) => CST;
/**
 * When applied to a class it creates a [frozen](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) instance of it,
 * thus preventing modifications to instance properties after instantiation.
 *
 * @example
 * ```ts
@Frozen
class Foo<T> {
  foo: T;
  bar?: MaybeUndefined<string>;

  constructor(foo: T) {
    this.foo = foo;
    this.bar = 'bar';
  }

  someFoo(): T {
    return this.foo;
  }
}

const foo = new Foo('foo');
// The line below will cause a TypeError: Cannot assign to read only property 'bar'
foo.bar = 'altered bar';
// The line below will cause a TypeError: Cannot delete property 'bar'
delete foo.bar;
 * ```
 */
declare function Frozen<T extends Newable>(cst: T): T & Newable;
/**
 * When applied to a class, it creates a [sealed](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal) instance of it,
 * preventing extensions and making existing properties non-configurable.
 *
 * @example
 * ```ts
 * @Sealed
 * class Person {
 *   constructor(public name: string, public age?: number) {}
 * }
 *
 * const john = new Person('John', 30);
 * // Trying to add a new property will throw an error
 * (john as any).email = 'john@example.com'; // TypeError: Cannot add property email, object is not extensible
 *
 * // Existing properties can still be modified
 * john.age = 31; // Allowed
 *
 * // Existing properties cannot be re-configured or deleted
 * delete john.age; // TypeError: Cannot delete property 'age'
 * }
 * ```
 * */
declare function Sealed<T extends Newable>(cst: T): T & Newable;
/**
 * When applied to a class, it ensures that only a single instance of the class can be created.
 * If an attempt is made to create another instance, the existing instance will be returned.
 *
 * @remarks
 * The `Singleton` pattern is often used for cases where a global state or resource needs to be shared across the entire application.
 * It is common in cases like configuration settings or managing connections to a shared resource (e.g., a database or API).
 *
 * @example
 * ```ts
 * @Singleton
 * class Database {
 *   constructor(public host: string, public port: number) {}
 * }
 *
 * const db1 = new Database('localhost', 5432);
 * const db2 = new Database('localhost', 5432);
 *
 * console.log(db1 === db2); // true, both db1 and db2 refer to the same instance
 * ```
 * @see
 * https://en.wikipedia.org/wiki/Singleton_pattern
 */
declare function Singleton<T extends Newable>(cst: T): T;

export { type Abs, type And, type AnyFunction, type Assign, type CapitalizeFirst, type DeepImmutable, type DeepMutable, type DeepNotRequired, type DeepOmit, type DeepPick, type DeepRequired, type DeepToPrimitive, type EitherOneOrMany, type EmptyObject, type EnforcedString, type EqualStrlen, type Equals, type Even, type ExcludeNull, type ExcludeNullable, type ExcludeUndefined, type ExclusiveUnion, type Extends, type Falsy, type FalsyProperties, type FilterBy, Final, FinalTypeError, type Flip, type Float, Frozen, type If, type IfEquals, type IfExtends, type ImmutableKeys, type Integer, type IsAnyFunction, type IsArray, type IsArrayIncludesTypeof, type IsBigInt, type IsBoolean, type IsDeepImmutable, type IsDeepMutable, type IsDeepNotRequired, type IsDeepRequired, type IsExactlyAny, type IsExactlyBigInt, type IsExactlyNumber, type IsExactlyString, type IsExactlySymbol, type IsExactlyUnknown, type IsFalsy, type IsFloat, type IsFunction, type IsInteger, type IsNegative, type IsNegativeFloat, type IsNegativeInteger, type IsNever, type IsNewable, type IsNullable, type IsNumber, type IsNumeric, type IsObject, type IsPositive, type IsPositiveFloat, type IsPositiveInteger, type IsString, type IsSymbol, type IsTruthy, type IsUnknown, type Keys, type KeysToValues, type Maybe, type MaybeUndefined, type MaybeUnknown, type Methods, type MutableKeys, type Nand, type NegativeFloat, type NegativeFloatString, type NegativeInteger, type NegativeIntegerString, type NewType, type Newable, type NonRequiredKeys, type Not, type NotIncluded, type Nullable, type Numeric, type NumerifyString, type Odd, type OmitByType, type OmitCommonKeys, type OmitExactlyByTypeDeep, type Optional, type Or, type PartialExcept, type PickByType, type PickCommonKeys, type PickExactlyByType, type PositiveFloat, type PositiveFloatString, type PositiveInteger, type PositiveIntegerString, type PositiveRange, type Primitive, type Properties, type Prune, type ReplaceKeys, type RequiredKeys, Sealed, type Simplify, Singleton, type SizedTuple, type StringEndsWith, type StringStartsWith, type StringifyPrimitive, type Strlen, type TestType, type TruthyProperties, type Tuple, type UnassignableTypeError, type UnionToIntersection, type UnionToTuple, type UniqueArray, type UnknownFunction, type Vals, type Xor };
