UNPKG

ts-roids

Version:
2,113 lines (2,109 loc) 79.7 kB
/** * 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 exte