// NOTE: code now moved to https://github.com/tycho01/typical // older revision left here, but it no longer runs well in TS Playground export type Obj = { [k: string]: T }; export type NumObj = { [k: number]: T }; // export type List = ArrayLike; // no unapplied generic types :( export type List = ArrayLike; // progress: https://github.com/Microsoft/TypeScript/issues/16392 export function force() {} // export function force1() {} export type SafeArr = R & Array<{[K in Name]: Param }>; export type SafeObj, Name extends string> = O & Obj; // , Param extends string // Obj<{[K in Name]: Param }> export type SwitchObj> = SafeObj[Param]; // , Param // export type SwitchArr*/> = SafeArr[Param]; // ^ #15768, TS2536 `X cannot be used to index Y` on generic // ^ comment Array constraint to allow use of Partial // export type ObjectProp, K extends string> = O[K]; // trivial export type ObjectHasKey< O extends {}, K extends string > = ({[K in keyof O]: '1' } & Obj<'0'>)[K]; force<'1', ObjectHasKey<{a:1}, 'a'>>() force<'0', ObjectHasKey<{a:1}, 'a'>>() type oHasOT = ObjectHasKey<{a:1}, 'a'>; type oHasOF = ObjectHasKey<{a:1}, 'b'>; type oHasOM = ObjectHasKey<{a?:1}, 'a'>; type sdkhfjsdkj = Simplify<{a?:1}> type shjksadsd = {a?:1}['a'] type asdfhjks = keyof {a?:1} // type oHasRT = ObjectHasKey; // type oHasRF = ObjectHasKey; export type TupleHasIndex< Arr extends List, I extends number > = ({[K in keyof Arr]: '1' } & Array<'0'>)[I]; // ^ #15768, TS2536 `X cannot be used to index Y` on generic type myArr = [1, 2, 3]; type hasT = TupleHasIndex; type hasF = TupleHasIndex; // type hasT = TupleHasIndex<{a:1}, 'a'>; // type hasF = TupleHasIndex<{a:1}, 'b'>; // type hasOT = TupleHasIndex<{ 1: "hi" }, 1>; // type hasOF = TupleHasIndex<{ 1: "hi" }, -1>; export type IsArrayType = DefinitelyYes> type IsArrayT = IsArrayType; type IsArrayR = IsArrayType; type IsArrayO = IsArrayType<{ length: 2 }>; export type HasKey = If, TupleHasIndex, ObjectHasKey>; // ^ Type 'T' does not satisfy the constraint 'any[]'. // ^ Type 'K' does not satisfy the constraint 'string'. type HasKeyR = HasKey; type HasKeyTT = HasKey; type HasKeyTF = HasKey; type HasKeyOT = HasKey<{ a: 1 }, 'a'>; type HasKeyOF = HasKey<{ a: 1 }, 'b'>; // Bool: Not, And, Or, Eq, Neq export type Not = SwitchObj; // export type Not = { '1': '0'; '0': '1'; }; type not0 = Not<'0'>; type not1 = Not<'1'>; type not2 = Not<'2'>; // type notT = Not<'true'>; // type notF = Not<'false'>; type notA = Not; type notN = Not; // any // type notT_ = Not; // any // type notF_ = Not; // any export type And< A extends string, B extends string > = ({ 1: { 1: '1' } & Obj<'0'> } & Obj>)[A][B]; type andT = And<'1', '1'>; type andF = And<'0', '1'>; export type Or = ({ 0: { 0: '0' } & Obj<'1'> } & Obj>)[A][B]; type orT = Or<'1', '0'>; type orF = Or<'0', '0'>; export type BEq< A extends string, B extends string > = ({ [K in A]: '1' } & Obj<'0'>)[B]; type eq0 = BEq<'0', '0'>; type eq1 = BEq<'0', '1'>; type eq2 = BEq<'1', '0'>; type eq3 = BEq<'1', '1'>; export type Neq< A extends string, B extends string > = Not>; // Type: InstanceOf, Matches, Equal // // throwing Matches // let f = (v: T) => true; interface isT { (v: T): '1'; (v: any): '0'; } // export type Matches = typeof isT(V); // // ^ this is where things fail until #6606 // let isBool: isT // let falseBool = isBool(false) // 1 // let trueBool = isBool(true) // 1 // let anyBool = isBool( 0) // 0 // let neverBool = isBool( 0) // 1... // // ^ `never` qualifies as anything... may need to rethink this. // export type Equal = And, Matches>; // export type InstanceOf = And, Not>>; // Casts: ToBool, NumberToString, NumberToBits, BitsToNumber export type Falsy = undefined | null | 0 | '' | void | never; // type IsFalsy = Matches // type IsTruthy = Not> // type ToBool = IsTruthy // Bits: export type ArrayProp> = R[-1]; type ArrayPropTest = ArrayProp>; // export type TupleProp, I extends number> = SwitchArr>; // type TuplePropA = TupleProp<[0], 0>; // type TuplePropB = TupleProp<[0], 1>; // // type TuplePropC = TupleProp<[], 0>; // A tuple type element list cannot be empty. // type TuplePropD = TupleProp; // single: Length, Left, Right, Invert // Combine two: BAnd, BOr, Xor // Combine two, for ordinals like number: Append, Add, Subtract, Multiply, Divide, Modulo, Max, Min // Ordinal equalities: Gt, Gte, Lt, Lte, Eq // ^ thru Type equalities? similar but can't do any/never input here export type Union2Keys = UnionToObject & Obj; export type Obj2Keys = {[K in keyof T]: K } & Obj; export type Arr2Keys = {[K in keyof T]: K } & Obj; export type Keyed = {[K in keyof T]: K }; // need to figure out from the ground up which ops fail for toString: // keyof - ok // in - ok // access - not ok // {}[|] // {}[&] // ({}|{})[] // ({}&{})[] // & // | export type UnionHasKey = ({[S in Union]: '1' } & Obj<'0'>)[K]; // export type UnionHasKey = And<({[S in Union]: '1' } & Obj<'0'>)[K], ({[S in K]: '1' } & Obj<'0'>)[Union]>; type UnionHasT = UnionHasKey<'a'|'b', 'b'>; type UnionHasF = UnionHasKey<'a'|'b', 'c'>; type UnionHasTT = UnionHasKey<'a'|'b', 'a'|'b'>; type UnionHasFF = UnionHasKey<'a'|'b', 'c'|'d'>; type UnionHasTF = UnionHasKey<'a'|'b', 'b'|'c'>; // v these fail hard: type UnionHasTS = UnionHasKey<'a'|'b'|'toString', 'toString'>; type UnionHasFS = UnionHasKey<'a'|'b', 'toString'>; type skjdfds = keyof Simplify<{ [P in ('a' | 'b') & ('b' | 'c')]: "1" }> export type Indeterminate = And, '0'>, ObjectHasKey, '1'>>; export type Determinate = Not>; export type DefinitelyYes = And>; export type DefinitelyNo = And, Determinate>; export type If = { 1: Then, 0: Else }[Cond]; export type UnionToObject = { [K in Keys]: K }; type TestUnion2Obj = Obj2Keys>; export type IntersectionUnions = Obj2Keys>[Big] /*!*/; // type TestUnionInt2 = IntersectionUnions<1|2|3, 2|3|4>; // only strings allowed type TestUnionInt1T = IntersectionUnions<'a' | 'b' | 'c', 'b' | 'c' | 'd'>; type TestUnionInt1F = IntersectionUnions<'a' | 'b' | 'c', 'x' | 'z' | 'd'>; // type sdkflsd = {a:1}[never] // how do I may string/never to 1/0? export type UnionContained = DefinitelyYes<({ [P in U]: '1' } & Obj<'0'>)[T | U]>; type ijdkj1 = UnionContained; type ijdkj2 = UnionContained<'a', 'a'>; type ijdkj3 = UnionContained<'b', 'a'>; type ijdkj4 = UnionContained<'a' | 'b', 'a'>; export type UnionEmpty = And, UnionContained>; type EmptyT = UnionEmpty; type EmptyF = UnionEmpty<'a'>; type EmptyF2 = UnionEmpty<'c'>; type EmptyFF = UnionEmpty<'a' | 'b'>; type EmptyFFF = UnionEmpty<'a' | 'b' | 'c' | 'd'>; type EmptyFF2 = UnionEmpty<'c' | 'd'>; type EmptyS = UnionEmpty<'toString'>; type EmptyS2 = UnionEmpty<'toString' | 'a'>; export type UnionsOverlap = Not>>; type OverlapT = UnionsOverlap<'a', 'a' | 'b'>; type OverlapF = UnionsOverlap<'a', 'c'>; export type ObjectHasKeySafe = UnionsOverlap; type ObjectHasKeySafeT = ObjectHasKeySafe<{ a: 1 }, 'a'>; type ObjectHasKeySafeF = ObjectHasKeySafe<{ a: 1 }, 'b'>; type ObjectHasKeySafeTF = ObjectHasKeySafe<{ a: 1 }, 'a' | 'b'>; // 1 type ObjectHasKeySafeST = ObjectHasKeySafe<{ a: 1, toString(): string }, 'a'>; type ObjectHasKeySafeSF = ObjectHasKeySafe<{ a: 1, toString(): string }, 'b'>; // 1 :() ////////////////////////////////////////// type ObjectHasKeySafeSTF = ObjectHasKeySafe<{ a: 1, toString(): string }, 'a' | 'b'>; // 1 type ObjectHasKeySafeTS = ObjectHasKeySafe<{ a: 1 }, 'toString'>; type ObjectHasKeySafeFST = ObjectHasKeySafe<{ a: 1 }, 'toString' | 'a'>; // 1 type ObjectHasKeySafeFS = ObjectHasKeySafe<{ a: 1 }, 'toString' | 'b'>; type ObjectHasKeySafeTSF = ObjectHasKeySafe<{ a: 1 }, 'toString' | 'a' | 'b'>; type ObjectHasKeySafeSST = ObjectHasKeySafe<{ a: 1, toString(): string }, 'toString'>; type ObjectHasKeySafeSSTA = ObjectHasKeySafe<{ a: 1, toString(): string }, 'toString' | 'a'>; type ObjectHasKeySafeSSF = ObjectHasKeySafe<{ a: 1, toString(): string }, 'toString' | 'b'>; type ObjectHasKeySafeSSTF = ObjectHasKeySafe<{ a: 1, toString(): string }, 'toString' | 'a' | 'b'>; export type ObjProp, K extends string, Default = never> = If, O[K], Default>; type ObjPropA = ObjProp<{ a: 1 }, 'a'>; type ObjPropB = ObjProp<{ a: 1 }, 'b'>; type ObjPropC = ObjProp<{ a: 1 }, 'toString'>; type ObjPropD = ObjProp<{ a: 1, toString(): string }, 'a'>; type ObjPropE = ObjProp<{ a: 1, toString(): string }, 'b'>; // any :( ////////////////////////// type ObjPropF = ObjProp<{ a: 1, toString(): string }, 'toString'>; // export type IsUnion = { [P in T]: UnionContained }//[T]; export type IsUnion< T extends string, O extends { [P in T]: UnionContained } = { [P in T]: UnionContained } > = O[T]; type IsUnionT = IsUnion<'a' | 'b'>; type IsUnionF = IsUnion<'a'>; type IsUnionFF = IsUnion; // type IsUnionU = IsUnion<'a' | undefined>; // export type Lambda = any; // export type TypeMap = Pick[Keys]; // // nope, no type lambdas -- can't have unapplied types // https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-307871458 // type sfsd = { [P in PrototypeMethods]: P; [k: string]: never; }; type sdkjdsl = { toString: "toString"; [P in keyof "a"]: never }; type sdkjds2l = { [P in keyof U]: never; [K in keyof PrototypeMethods]: K; }; export type Diff = ({[P in T]: P } & { [P in U]: never } & // toString: "toString"; toLocaleString: "toLocaleString"; { [k: string]: never })[T]; // needs TS 2.5 // toString: "toString"; toLocaleString: "toLocaleString"; type TestDiff = Diff<"a" | "b" | "c", "c" | "d">; // "a" | "b" type sdfslj = Diff<'a' | 'b' | 'toString', 'a'>; type sdfslk = Diff<'a' | 'b', 'a' | 'toString'>; export type UnionDiff_ = {[K in Big]: { 1: Union2Keys[K], 0: never }[Not>]}//[Big]; export type UnionDiff< Big extends string, Small extends string, Step extends UnionDiff_ = UnionDiff_ > = Step[Big]; type TestUnionDiff = UnionDiff<'a' | 'b' | 'c', 'b' | 'c' | 'd'>; type sdgslj = UnionDiff<'a' | 'b' | 'toString', 'a'>; type sdgslk = UnionDiff<'a' | 'b', 'a' | 'toString'>; type sdgslk2 = ObjectHasKey<{ a: 1 }, "toString">; type Item1 = { a: string, b: number, c: boolean }; type Item2 = { a: number }; export type Omit = Pick>; // {[P in Diff]: T[P]} type OmitTest = Omit // { b: number, c: boolean }; export type Overwrite = {[P in keyof T | keyof K]: { 1: T[P], 0: K[P] }[ObjectHasKey]}; // export type Overwrite = { [P in Diff]: T[P] } & U; // ^ no-dependency version by Anders, uses intersection // export type Overwrite]: T[P] } & U> = Pick; // ^ my attempt at cleaning out the intersection, somehow makes FromPairs/ZipObject fail type TestOverwrite = Overwrite // { a: number, b: number, c: boolean }; // keys optional in 2nd arg: works without `strictNullChecks` // intersection objs export type IntersectionObjectKeys = Pick, keyof A>[keyof A]; export type IntersectionObjects = Pick>; type Obj1 = { a: 1, b: 2 }; type Obj2 = { b: 'X', c: 'Z' }; type Int1 = IntersectionObjects; // { b: 2; } type Int2 = IntersectionObjects; // { b: 'X'; } export type ObjectValsToUnion = O[keyof O]; type ObjectValsToUnionTest = ObjectValsToUnion; // try for array with head so as to implement tail, array iteration, reduce, and traversables? type PrototypeMethods = 'toLocaleString' | 'toString' //| 'constructor' | 'hasOwnProperty' | 'isPrototypeOf' | 'propertyIsEnumerable' | 'valueOf' | '__defineGetter__' | '__defineSetter__' | '__lookupGetter__' | '__lookupSetter__' | '__proto__'; type Prototype = {[K in PrototypeMethods]: K }; // type PrototypeHas = ObjectHasKey; type ArrPrototypeMethods = 'length' | 'push' | 'pop' | 'concat' | 'join' | 'reverse' | 'shift' | 'slice' | 'sort' | 'splice' | 'unshift' | 'indexOf' | 'lastIndexOf' | 'every' | 'some' | 'forEach' | 'map' | 'filter' | 'reduce' | 'reduceRight' | 'find' | 'findIndex' | 'fill' | 'copyWithin' | 'entries' | 'keys' | 'values' // 'toLocaleString' | 'toString' | type ArrPrototype = {[K in ArrPrototypeMethods]: K }; type ArrPrototypeHas = ObjectHasKey; // difference arrs export type NumberToString = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','65','66','67','68','69','70','71','72','73','74','75','76','77','78','79','80','81','82','83','84','85','86','87','88','89','90','91','92','93','94','95','96','97','98','99','100','101','102','103','104','105','106','107','108','109','110','111','112','113','114','115','116','117','118','119','120','121','122','123','124','125','126','127','128','129','130','131','132','133','134','135','136','137','138','139','140','141','142','143','144','145','146','147','148','149','150','151','152','153','154','155','156','157','158','159','160','161','162','163','164','165','166','167','168','169','170','171','172','173','174','175','176','177','178','179','180','181','182','183','184','185','186','187','188','189','190','191','192','193','194','195','196','197','198','199','200','201','202','203','204','205','206','207','208','209','210','211','212','213','214','215','216','217','218','219','220','221','222','223','224','225','226','227','228','229','230','231','232','233','234','235','236','237','238','239','240','241','242','243','244','245','246','247','248','249','250','251','252','253','254','255']; // ^ R.pipe(R.range(0), R.map(JSON.stringify), JSON.stringify, R.replace(/"/g,"'"))(256) type NumberToStringTest = NumberToString[3]; type NumberToStringTest2 = NumberToString['3']; // type NumberToString = SafeArr<['0', '1', '2', '3', '4', '5'], 'invalidIndex', I>; // type NumberToStringTest = NumberToString<3>; // export type StringToNumber = {[N in number]: N }; export type StringToNumber = {0: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}; // ^ R.pipe(R.range(0), R.map(k => [k,k]), R.fromPairs, JSON.stringify, R.replace(/"/g,''))(256) type StringToNumberTest = StringToNumber['3']; export type Inc = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256]; // R.pipe(R.range(0), R.map(R.inc), JSON.stringify)(256) export type Dec = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254]; // R.pipe(R.range(0), R.map(R.dec), JSON.stringify)(256) // export type Dec = { 0: -1, 1: 0, 2: 1, 3: 2, 4: 3 }; export type Add< A extends number, B extends number > = { 1: A, 0: Add }[NumbersEqual<0, B>]; type TestAdd = Add<3, 2>; export type Subtract< A extends number, B extends number > = { 1: A, 0: Subtract }[NumbersEqual<0, B>]; type TestSubtract = Subtract<3, 2>; export type Mult< A extends number, B extends number, Acc extends number = 0 > = { 1: Acc, 0: Mult> }[NumbersEqual<0, B>]; type TestMult = Mult<3, 2>; export type Pow< Base extends number, Exp extends number, Acc extends number = 1 > = { 1: Acc, 0: Pow> }[NumbersEqual<0, Exp>]; type TestPowA = Pow<3, 2>; type TestPowB = Pow<2, 3>; export type DivFloor< A extends number, B extends number, Acc extends number = 0 > = { 0: Acc, 1: DivFloor, B, Inc[Acc]> }[Gt]; type TestDivFloor = DivFloor<5, 2>; export type Modulo< A extends number, B extends number, Acc extends number = 0 > = { 0: A, 1: Modulo, B, Inc[Acc]> }[Gt]; type TestModulo = Modulo<5, 2>; export type Gt< A extends number, B extends number > = { 1: '0', 0: If, '1', Gt>, }[NumbersEqual<0, A>]; type TestGtG = Gt<3, 2>; type TestGtL = Gt<2, 3>; type TestGtE = Gt<3, 3>; export type Lt< A extends number, B extends number > = { 1: '0', 0: If, '1', Lt>, }[NumbersEqual<0, B>]; type TestLtG = Lt<3, 2>; type TestLtL = Lt<2, 3>; type TestLtE = Lt<3, 3>; export type Gte< A extends number, B extends number > = { 1: '1', 0: If, '0', Gte>, }[NumbersEqual<0, B>]; type TestGteG = Gte<3, 2>; type TestGteL = Gte<2, 3>; type TestGteE = Gte<3, 3>; export type Lte< A extends number, B extends number > = { 1: '1', 0: If, '0', Lte>, }[NumbersEqual<0, A>]; type TestLteG = Lte<3, 2>; type TestLteL = Lte<2, 3>; type TestLteE = Lte<3, 3>; export type FirstIndex, I extends number = 0> = { 1: I, 0: FirstIndex }[ObjectHasKey]; type TestFirstIndex = FirstIndex<{ 2: 'a', 3: 'b' }>; export type IncIndex, N extends number, I extends number = 0 /*FirstIndex*/, Acc = { length: R['length'] }> = { 0: Acc, 1: IncIndex]]: R[I] }> }[ObjectHasKey]; type TestIncIndex = IncIndex<{ 0: 'a', 1: 'b', length: 2 }, 2>; export type DecIndex, N extends number, I extends number = FirstIndex, Acc = { length: R['length'] }> = { 0: Acc, 1: DecIndex]]: R[I] }> }[ObjectHasKey]; type TestIncIndex = DecIndex<{ 2: 'a', 3: 'b', length: 2 }, 2>; export type ZeroIndex, I extends number = FirstIndex> = /*If, R,*/ DecIndex//>; type TestIncIndex = ZeroIndex<{ 2: 'a', 3: 'b', length: 2 }, 2>; type TestArr = ['a', 'b', 'c']; export type TupleToObject, I extends number = 0, Acc = {}> = { 1: TupleToObject, 0: Simplify }[TupleHasIndex]; type Arr2ObjTest = TupleToObject; export type TupleToList, I extends number = 0, Acc = {}> = { 1: TupleToList, 0: Simplify }[TupleHasIndex]; type Arr2LikeTest = TupleToList; // export type NumObjToList = Length; export type NumObjToList> = O & { length: Length }; // export type NumObjToList> = Overwrite }>; // export type NumObjToList, Len extends Length = Length> = O & { length: Len }; // export type NumObjToList, Len extends Length = Length> = Overwrite; type TestNum2LikeA = NumObjToList<{ 0: 'a', 1: 'b' }>; type TestNum2LikeB = NumObjToList>; // ^ WRONG, length gives 0, see #16018 export type ListToNumObj> = Omit; type TestListToNumObj = ListToNumObj<{ 0: 'a', 1: 'b', length: 2 }>; export type AppendList< R extends List, T, Len extends number = LengthList > = Overwrite; type TestAppendList = AppendList<{ 0: 'a', 1: 'b', length: 2 }, 'c'>; export type AppendNumObj< R extends NumObj, T, Len extends number = Length > = R & { [P in NumberToString[Len]]: T }; type TestAppendNumObj = AppendNumObj<{ 0: 'a', 1: 'b' }, 'c'>; // ^ WRONG export type Prepend< R extends List, T > = { 0: T } & IncIndex; // presumes the list is already zero-indexed, otherwise needs ZeroIndex type TestPrepend = Prepend<{ 0: 'b', 1: 'c', length: 2 }, 'a'>; export type ConcatLists, B extends List> = Overwrite, { length: Add }>; type TestConcatLists = ConcatLists<{ 0: 'a', 1: 'b', length: 2 }, { 0: 'c', 1: 'd', length: 2 }>; export type ConcatNumObjs, B extends NumObj> = A & IncIndex; type TestConcatNumObjs = ConcatNumObjs<{ 0: 'a', 1: 'b' }, { 0: 'c', 1: 'd' }>; export type TupleToUnion, I extends number = 0, Acc = never> = { 1: TupleToUnion, 0: Acc }[TupleHasIndex]; type Arr2UnionTest = TupleToUnion; export type TupleIndicesToUnion, I extends number = 0, Acc = never> = { 1: TupleIndicesToUnion, 0: Acc }[TupleHasIndex]; type ArrKeys2UnionTest = TupleIndicesToUnion; export type LengthList> = R['length']; type TestVectorLength = LengthList<{ 0: 'a', 1: 'b', length: 2 }>; export type Length, I extends number = 0> = { 1: Length, 0: I }[ObjectHasKey]; type TestObjLength = Length>; type TestTplLength = Length; type TestArrLength = Length; type TestNumLength = Length<{ 0: 'a', 1: 'b' }>; export type Vector = { 1: Acc, 0: Vector }[NumbersEqual]; type TestVector = Vector; // export type TupleLastIndex = Dec[Length]; export type TupleLastIndex, I extends number = 0> = { 1: TupleLastIndex, 0: Dec[I] }[TupleHasIndex]; type TestLast = TupleLastIndex; type TestLastArr = TupleLastIndex; export type TupleLastElem, I extends number = 0> = { 1: TupleLastElem, 0: R[Dec[I]] }[TupleHasIndex]; type TestLastElem = TupleLastElem; // v useless type to demo backward iteration export type FirstElem, I extends number = Length, Prev extends number = Dec[I]> = { 1: FirstElem, 0: R[I] }[TupleHasIndex]; // ^ #15768, TS2536 `X cannot be used to index Y` on generic type TestFirstElem = FirstElem; // v useless type to demo backward iteration export type FirstIndex, I extends number = TupleLastIndex> = { 1: FirstIndex, 0: Inc[I] }[TupleHasIndex]; // ^ Generic type instantiation is excessively deep and possibly infinite type TestFirstIndex = FirstIndex; // ^ WRONG // Ramda functions listed in #12512 redone with iteration: export type PathFn, I extends number = 0> = { 1: PathFn, 0: T }[TupleHasIndex]; type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', 1, 'd']>; // "e" export declare function path>(obj: T, path: R): PathFn; let par1: { a: { b: ['c', { d: 'e' }] } }; let par2: ['a', 'b', 1, 'd']; const pathTest = path(par1, par2); // fails :(, should also yield "e" export type PathOrFn, I extends number = 0> = { 1: If, PathOrFn, Def>, 0: T }[TupleHasIndex]; type PathOrTestT = PathOrFn<{ a: { b: ['c', { d: 'e' }] } }, "oh", ['a', 'b', 1, 'd']>; // "e" type PathOrTestF = PathOrFn<{ a: { b: ['c', { d: 'e' }] } }, "oh", ['a', 'b', 4]>; // "oh" export type MergeAllFn>, I extends number = 0, T = {}> = { 1: MergeAllFn>, 0: T }[TupleHasIndex]; type MergeAllTest = MergeAllFn<[{ a: 1, b: 2 }, { b: 3, c: 4 }, { d: 5 }]>; // { a: 1, b: 3, c: 4, d: 5 } export type FromPairsFn, I extends number = 0, T = {}> = { 1: FromPairsFn>, 0: T }[TupleHasIndex]; type FromPairsTest = FromPairsFn<[['a', 1], ['b', 2], ['c', 3], ['a', 5]]>; // { a: 5, b: 2, c: 3 } export type ZipObjectFn, R2 extends List, I extends number = 0, T = {}> = { 1: ZipObjectFn>, 0: T }[TupleHasIndex]; type ZipObjectTest = ZipObjectFn<['a', 'b', 'c'], [1, 2, 3]>; // { a: 1, b: 2, c: 3 } export type ListFrom< R extends List, N extends number, I extends number = N, Acc extends List = { length: Subtract, I> } > = { 0: Acc, 1: ListFrom]]: R[I] }> }[TupleHasIndex]; type TestListFrom = ListFrom<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, 2>; export type ListTo< R extends List, N extends number, I extends number = 0, Acc extends List = { length: N } > = { 0: Acc, 1: ListTo }[NumbersEqual]; type TestListTo = ListTo<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, 2>; export type ListTail> = ListFrom; type TestListTail = ListTail<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }>; export type DifferenceLists, Small extends List> = ListFrom>; type TestDifferenceLists = DifferenceLists<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, { 0: 123, 1: 456, length: 2 }>; // `...` needs #5453, so syntax errors: // export type TupleFrom, I extends number, Acc extends List = []> = // { 0: Acc, 1: TupleFrom }[TupleHasIndex]; // type TestTupleFrom = TupleFrom<['a', 'b', 'c', 'd'], 2>; // export type TupleTo, To extends number, I extends number = 0, Acc extends List=[]> = // If, { 0: Acc; 1: TupleTo; }[NumbersEqual], T>; // type TestTupleTo = TupleTo<['a', 'b', 'c', 'd'], 2>; // export type TupleTail> = TupleFrom; // type TestTupleTail = TupleTail<['a', 'b', 'c']>; // export type DifferenceTuples, Small extends List> = TupleFrom>; // type TestDifferenceTuples = DifferenceTuples<['a', 'b', 'c', 'd'], [123, 456]>; export type StringsEqual< A extends string, B extends string > = ObjectHasKey<{[P in A]: 'hi' }, B>; type StringsEqualT = StringsEqual<'a', 'a'>; type StringsEqualF = StringsEqual<'a', 'b'>; // type NumbersEqual = ObjectHasKey<{ [P in NumberToString[A]]: 'hi' }, NumberToString[B]>; export type NumbersEqual< A extends number, B extends number > = DefinitelyYes>; // ^ #15768, TS2536 `X cannot be used to index Y` on generic type NumbersEqualT = NumbersEqual<123, 123>; type NumbersEqualF = NumbersEqual<123, 456>; // type NumbersEqualTA = NumbersEqual<123, '123'>; // type NumbersEqualTB = NumbersEqual<'123', 123>; type NumbersEqualFC = NumbersEqual<0, 5>; type NumbersEqualFD = NumbersEqual<5, 0>; export type Simplify = Pick; type abc = { a: 1, b: 2, foo: () => string, toString: () => string, toLocaleString: () => string } type bcd = Omit; type bdd = Omit; type ccd = Simplify; type ccg = Simplify; type crd = Simplify; type crg = Simplify; type cqd = Simplify; type cqg = Simplify; type dcd = Overwrite; type dcg = Overwrite; type dcf = Overwrite; type dch = Overwrite; type duf = Overwrite; type duh = Overwrite; type cdd = Simplify; type bce = Omit; type ItemA = { a: string, b: number, c: boolean, toString(): string }; type KeyedItem1 = keyof ItemA type DiffedItem1 = Diff type OmittedItem1 = Omit // should be { b: number, c: boolean, toString(): string } // is { b: number; c: boolean; } type OmittedItem2 = keyof Omit // "b" | "c" | ("toString" & (() => string)) // ^ it actually lied about "toString" being gone; it's just no longer showing because its key is somehow no longer just a string?! // #16072 declare function comp(f: (x: A) => B, g: (x: B) => C): (x: A) => C const wrapper = comp(x => [x], y => ({ p: y })); // (x: {}) => { p: {}[] } // #12838 declare function inc(n: number): number; // +1 declare function identity(a: T): T; declare function compose(fn0: (x0: V0) => T1): (x0: V0) => T1; declare function compose(fn1: (x: T1) => T2, fn0: (x: V0) => T1): (x: V0) => T2; declare function pipe (fn0: (x0: V0) => T1): (x0: V0) => T1; // arity 1: same as compose declare function pipe (fn0: (x: V0) => T1, fn1: (x: T1) => T2): (x: V0) => T2; // arity 2: params swapped // don't use generics if it can't resolve them right away: compose(identity) // generics lost, now {} => {} pipe (identity) // ditto // argument order apparently matters too: pipe (inc, identity); // ok, number -> number compose(identity, inc); // nope, number => {} // also no reasoning backward: compose(inc, identity); // {} => number pipe (identity, inc); // {} => number type AddPrototype = Pick; type ArrProto> = AddPrototype & { [Symbol.iterator]: () => IterableIterator, [Symbol.unscopables]: () => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; } } & { [i: number]: T[-1] }; // #6229 const foo: [1, "a"] = [1, "a"]; // no cast with #16389 var t3: TupleToObject = foo; t3[2]; // error var t1: [number, string] = >[1, "a"]; // ^ ok // v make either of these error: var t5a: [number, string] = [1, "a", "b"]; var t5b: [number, string] = > [1, "a", "b"]; var t5c: TupleToObject<[number, string]> = [1, "a", "b"]; var t5d: TupleToObject<[number, string]> = > [1, "a", "b"]; var t5e: TupleToObject<[number, string]> = > [1, "a", "b"]; // test interplay types type asdfInt = ({ a: 1 } & { c: 4 } & { b: 2, a: string } & { [k: string]: 3 })['a'] // objects considered merged, indexes ignored but real results intersect'd type asdfUnn = ({ a: 1 } /*| { c: 4 }*/ | { b: 2, a: string } /*| { [k: string]: 3 }*/)['a']; // ^ union of results; each object must *explicitly* contain key, no indexes type afdsfUnn = { a: 1, b: 2, c: 3 }['a' | 'b' /*| 'd'*/]; // ^ union of results, keys must all be contained type afdsfInt = { a: 1, b: 2, c: 3 }['a' /*& 'b'*/]; // impossible key