-
-
Save babakness/8fd1892c91b5680f76d211d4b7e4a2cc to your computer and use it in GitHub Desktop.
Type-level standard library for TypeScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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<T> = { [k: string]: T }; | |
export type NumObj<T> = { [k: number]: T }; | |
// export type List = ArrayLike; // no unapplied generic types :( | |
export type List<T> = ArrayLike<T>; | |
// progress: https://github.com/Microsoft/TypeScript/issues/16392 | |
export function force<T, V extends T>() {} | |
// export function force1<T extends '1'>() {} | |
export type SafeArr<R extends { [i: number]: any }, Name extends string, Param extends number> = R & Array<{[K in Name]: Param }>; | |
export type SafeObj<O extends Obj<any>, Name extends string> = O & Obj<Name>; // , Param extends string // Obj<{[K in Name]: Param }> | |
export type SwitchObj<Param extends string, Name extends string, O extends Obj<any>> = SafeObj<O, Name>[Param]; // , Param | |
// export type SwitchArr<Param extends number, Name extends string, R /*extends List<any>*/> = SafeArr<R, Name, Param>[Param]; | |
// ^ #15768, TS2536 `X cannot be used to index Y` on generic | |
// ^ comment Array constraint to allow use of Partial<myArr> | |
// export type ObjectProp<O extends Obj<any>, 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<myArr, 1>; | |
// type oHasRF = ObjectHasKey<myArr, -1>; | |
export type TupleHasIndex< | |
Arr extends List<any>, | |
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<myArr, 1>; | |
type hasF = TupleHasIndex<myArr, -1>; | |
// 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<T> = DefinitelyYes<ObjectHasKey<T, ArrPrototypeMethods>> | |
type IsArrayT = IsArrayType<myArr>; | |
type IsArrayR = IsArrayType<any[]>; | |
type IsArrayO = IsArrayType<{ length: 2 }>; | |
export type HasKey<T, K> = If<IsArrayType<T>, TupleHasIndex<T, K>, ObjectHasKey<T, K>>; | |
// ^ Type 'T' does not satisfy the constraint 'any[]'. | |
// ^ Type 'K' does not satisfy the constraint 'string'. | |
type HasKeyR = HasKey<any[], 2>; | |
type HasKeyTT = HasKey<myArr, 2>; | |
type HasKeyTF = HasKey<myArr, 5>; | |
type HasKeyOT = HasKey<{ a: 1 }, 'a'>; | |
type HasKeyOF = HasKey<{ a: 1 }, 'b'>; | |
// Bool: Not, And, Or, Eq, Neq | |
export type Not<T extends string> = SwitchObj<T, 'InvalidNotParam', { | |
'1': '0'; | |
'0': '1'; | |
}>; | |
// export type Not<T extends string> = { '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<any>; | |
type notN = Not<never>; // any | |
// type notT_ = Not<true>; // any | |
// type notF_ = Not<false>; // any | |
export type And< | |
A extends string, | |
B extends string | |
> = ({ 1: { 1: '1' } & Obj<'0'> } & Obj<Obj<'0'>>)[A][B]; | |
type andT = And<'1', '1'>; | |
type andF = And<'0', '1'>; | |
export type Or<A, B> = ({ 0: { 0: '0' } & Obj<'1'> } & Obj<Obj<'1'>>)[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<BEq<A, B>>; | |
// Type: InstanceOf, Matches, Equal | |
// // throwing Matches | |
// let f = <T>(v: T) => true; | |
interface isT<T> { | |
(v: T): '1'; | |
(v: any): '0'; | |
} | |
// export type Matches<V, T> = typeof isT<T>(V); | |
// // ^ this is where things fail until #6606 | |
// let isBool: isT<boolean> | |
// let falseBool = isBool(false) // 1 | |
// let trueBool = isBool(true) // 1 | |
// let anyBool = isBool(<any> 0) // 0 | |
// let neverBool = isBool(<never> 0) // 1... | |
// // ^ `never` qualifies as anything... may need to rethink this. | |
// export type Equal<A, B> = And<Matches<A, B>, Matches<B, A>>; | |
// export type InstanceOf<V, T> = And<Matches<V, T>, Not<Matches<T, V>>>; | |
// Casts: ToBool, NumberToString, NumberToBits, BitsToNumber | |
export type Falsy = undefined | null | 0 | '' | void | never; | |
// type IsFalsy<V> = Matches<V, Falsy> | |
// type IsTruthy<V> = Not<IsFalsy<V>> | |
// type ToBool = IsTruthy | |
// Bits: | |
export type ArrayProp<R extends List<any>> = R[-1]; | |
type ArrayPropTest = ArrayProp<Array<0>>; | |
// export type TupleProp<Arr extends List<any>, I extends number> = SwitchArr<I, 'indexNotInArray', Partial<Arr>>; | |
// 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<number[], 0>; | |
// 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<T extends string> = UnionToObject<T> & Obj<never>; | |
export type Obj2Keys<T> = {[K in keyof T]: K } & Obj<never>; | |
export type Arr2Keys<T> = {[K in keyof T]: K } & Obj<never>; | |
export type Keyed<T> = {[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<Union extends string, K extends string> = ({[S in Union]: '1' } & Obj<'0'>)[K]; | |
// export type UnionHasKey<Union extends string, K extends string> = 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<T extends string> = And<ObjectHasKey<UnionToObject<T>, '0'>, ObjectHasKey<UnionToObject<T>, '1'>>; | |
export type Determinate<T extends string> = Not<Indeterminate<T>>; | |
export type DefinitelyYes<T extends string> = And<T, Determinate<T>>; | |
export type DefinitelyNo<T extends string> = And<Not<T>, Determinate<T>>; | |
export type If<Cond extends '0' | '1', Then, Else> = { 1: Then, 0: Else }[Cond]; | |
export type UnionToObject<Keys extends string> = { [K in Keys]: K }; | |
type TestUnion2Obj = Obj2Keys<UnionToObject<'b' | 'c'>>; | |
export type IntersectionUnions<Big extends string, Small extends string> = Obj2Keys<UnionToObject<Small>>[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<T extends string, U extends string> = DefinitelyYes<({ [P in U]: '1' } & Obj<'0'>)[T | U]>; | |
type ijdkj1 = UnionContained<never, 'a'>; | |
type ijdkj2 = UnionContained<'a', 'a'>; | |
type ijdkj3 = UnionContained<'b', 'a'>; | |
type ijdkj4 = UnionContained<'a' | 'b', 'a'>; | |
export type UnionEmpty<T extends string> = And<UnionContained<T, 'a'>, UnionContained<T, 'b'>>; | |
type EmptyT = UnionEmpty<never>; | |
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<Big extends string, Small extends string> = Not<UnionEmpty<IntersectionUnions<Big, Small>>>; | |
type OverlapT = UnionsOverlap<'a', 'a' | 'b'>; | |
type OverlapF = UnionsOverlap<'a', 'c'>; | |
export type ObjectHasKeySafe<O extends object, K extends string> = UnionsOverlap<keyof O, K>; | |
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<O extends Obj<any>, K extends string, Default = never> = If<ObjectHasKeySafe<O, K>, 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<T extends string> = { [P in T]: UnionContained<T, P> }//[T]; | |
export type IsUnion< | |
T extends string, | |
O extends { [P in T]: UnionContained<T, P> } | |
= { [P in T]: UnionContained<T, P> } | |
> = O[T]; | |
type IsUnionT = IsUnion<'a' | 'b'>; | |
type IsUnionF = IsUnion<'a'>; | |
type IsUnionFF = IsUnion<never>; | |
// type IsUnionU = IsUnion<'a' | undefined>; | |
// export type Lambda<K> = any; | |
// export type TypeMap<F extends Lambda, Keys extends string> = Pick<F, Keys>[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<T extends string, U extends string> = | |
({[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_<Big extends string, Small extends string> = | |
{[K in Big]: { 1: Union2Keys<Big>[K], 0: never }[Not<UnionHasKey<Small, K>>]}//[Big]; | |
export type UnionDiff< | |
Big extends string, | |
Small extends string, | |
Step extends UnionDiff_<Big, Small> = UnionDiff_<Big, Small> | |
> = 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<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>; // {[P in Diff<keyof T, K>]: T[P]} | |
type OmitTest = Omit<Item1, "a"> // { b: number, c: boolean }; | |
export type Overwrite<K, T> = {[P in keyof T | keyof K]: { 1: T[P], 0: K[P] }[ObjectHasKey<T, P>]}; | |
// export type Overwrite<T, U> = { [P in Diff<keyof T, keyof U>]: T[P] } & U; | |
// ^ no-dependency version by Anders, uses intersection | |
// export type Overwrite<T, U, Int = { [P in Diff<keyof T, keyof U>]: T[P] } & U> = Pick<Int, keyof Int>; | |
// ^ my attempt at cleaning out the intersection, somehow makes FromPairs/ZipObject fail | |
type TestOverwrite = Overwrite<Item1, Item2> // { a: number, b: number, c: boolean }; | |
// keys optional in 2nd arg: works without `strictNullChecks` | |
// intersection objs | |
export type IntersectionObjectKeys<A, B> = Pick<Obj2Keys<B>, keyof A>[keyof A]; | |
export type IntersectionObjects<A, B> = Pick<A, IntersectionObjectKeys<A, B>>; | |
type Obj1 = { a: 1, b: 2 }; | |
type Obj2 = { b: 'X', c: 'Z' }; | |
type Int1 = IntersectionObjects<Obj1, Obj2>; | |
// { b: 2; } | |
type Int2 = IntersectionObjects<Obj2, Obj1>; | |
// { b: 'X'; } | |
export type ObjectValsToUnion<O> = O[keyof O]; | |
type ObjectValsToUnionTest = ObjectValsToUnion<Obj1>; | |
// 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<K extends string> = ObjectHasKey<Prototype, K>; | |
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<K extends string> = ObjectHasKey<ArrPrototype, K>; | |
// 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<I extends number> = 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<Inc[A], Dec[B]> }[NumbersEqual<0, B>]; | |
type TestAdd = Add<3, 2>; | |
export type Subtract< | |
A extends number, | |
B extends number | |
> = { 1: A, 0: Subtract<Dec[A], Dec[B]> }[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<A, Dec[B], Add<Acc, A>> }[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<Base, Dec[Exp], Mult<Acc, Base>> }[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<Subtract<A, B>, B, Inc[Acc]> }[Gt<A, B>]; | |
type TestDivFloor = DivFloor<5, 2>; | |
export type Modulo< | |
A extends number, | |
B extends number, | |
Acc extends number = 0 | |
> = { 0: A, 1: Modulo<Subtract<A, B>, B, Inc[Acc]> }[Gt<A, B>]; | |
type TestModulo = Modulo<5, 2>; | |
export type Gt< | |
A extends number, | |
B extends number | |
> = { | |
1: '0', | |
0: If<NumbersEqual<0, B>, '1', Gt<Dec[A], Dec[B]>>, | |
}[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<NumbersEqual<0, A>, '1', Lt<Dec[A], Dec[B]>>, | |
}[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<NumbersEqual<0, A>, '0', Gte<Dec[A], Dec[B]>>, | |
}[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<NumbersEqual<0, B>, '0', Lte<Dec[A], Dec[B]>>, | |
}[NumbersEqual<0, A>]; | |
type TestLteG = Lte<3, 2>; | |
type TestLteL = Lte<2, 3>; | |
type TestLteE = Lte<3, 3>; | |
export type FirstIndex<R extends NumObj<any>, I extends number = 0> = | |
{ 1: I, 0: FirstIndex<R, Inc[I]> }[ObjectHasKey<R, I>]; | |
type TestFirstIndex = FirstIndex<{ 2: 'a', 3: 'b' }>; | |
export type IncIndex<R extends List<any>, N extends number, I extends number = 0 /*FirstIndex<R>*/, Acc = { length: R['length'] }> = | |
{ 0: Acc, 1: IncIndex<R, N, Inc[I], Acc & { [P in NumberToString[Add<I, N>]]: R[I] }> }[ObjectHasKey<R, I>]; | |
type TestIncIndex = IncIndex<{ 0: 'a', 1: 'b', length: 2 }, 2>; | |
export type DecIndex<R extends List<any>, N extends number, I extends number = FirstIndex<R>, Acc = { length: R['length'] }> = | |
{ 0: Acc, 1: DecIndex<R, N, Inc[I], Acc & { [P in NumberToString[Subtract<I, N>]]: R[I] }> }[ObjectHasKey<R, I>]; | |
type TestIncIndex = DecIndex<{ 2: 'a', 3: 'b', length: 2 }, 2>; | |
export type ZeroIndex<R extends List<any>, I extends number = FirstIndex<R>> = /*If<ObjectHasKey<R, 0>, R,*/ DecIndex<R, I, I>//>; | |
type TestIncIndex = ZeroIndex<{ 2: 'a', 3: 'b', length: 2 }, 2>; | |
type TestArr = ['a', 'b', 'c']; | |
export type TupleToObject<R extends List<any>, I extends number = 0, Acc = {}> = | |
{ 1: TupleToObject<R, Inc[I], Acc & { [P in NumberToString[I]]: R[I] }>, 0: Simplify<Acc> }[TupleHasIndex<R, I>]; | |
type Arr2ObjTest = TupleToObject<TestArr>; | |
export type TupleToList<R extends List<any>, I extends number = 0, Acc = {}> = | |
{ 1: TupleToList<R, Inc[I], Acc & { [P in NumberToString[I]]: R[I] }>, 0: Simplify<Acc & { length: I }> }[TupleHasIndex<R, I>]; | |
type Arr2LikeTest = TupleToList<TestArr>; | |
// export type NumObjToList<O> = Length<O>; | |
export type NumObjToList<O extends NumObj<any>> = O & { length: Length<O> }; | |
// export type NumObjToList<O extends NumObj<any>> = Overwrite<O, { length: Length<O> }>; | |
// export type NumObjToList<O extends NumObj<any>, Len extends Length<O> = Length<O>> = O & { length: Len }; | |
// export type NumObjToList<O extends NumObj<any>, Len extends Length<O> = Length<O>> = Overwrite<O, { length: Len }>; | |
type TestNum2LikeA = NumObjToList<{ 0: 'a', 1: 'b' }>; | |
type TestNum2LikeB = NumObjToList<TupleToObject<TestArr>>; | |
// ^ WRONG, length gives 0, see #16018 | |
export type ListToNumObj<R extends List<any>> = Omit<R, 'length'>; | |
type TestListToNumObj = ListToNumObj<{ 0: 'a', 1: 'b', length: 2 }>; | |
export type AppendList< | |
R extends List<any>, | |
T, | |
Len extends number = LengthList<R> | |
> = Overwrite<R & { [P in NumberToString[Len]]: T }, { length: Inc[Len] }>; | |
type TestAppendList = AppendList<{ 0: 'a', 1: 'b', length: 2 }, 'c'>; | |
export type AppendNumObj< | |
R extends NumObj<any>, | |
T, | |
Len extends number = Length<R> | |
> = R & { [P in NumberToString[Len]]: T }; | |
type TestAppendNumObj = AppendNumObj<{ 0: 'a', 1: 'b' }, 'c'>; | |
// ^ WRONG | |
export type Prepend< | |
R extends List<any>, | |
T | |
> = { 0: T } & IncIndex<R, 1>; | |
// presumes the list is already zero-indexed, otherwise needs ZeroIndex | |
type TestPrepend = Prepend<{ 0: 'b', 1: 'c', length: 2 }, 'a'>; | |
export type ConcatLists<A extends List<any>, B extends List<any>> = | |
Overwrite<A & IncIndex<B, A['length']>, { length: Add<A['length'], B['length']> }>; | |
type TestConcatLists = ConcatLists<{ 0: 'a', 1: 'b', length: 2 }, { 0: 'c', 1: 'd', length: 2 }>; | |
export type ConcatNumObjs<A extends NumObj<any>, B extends NumObj<any>> = | |
A & IncIndex<B, Length<A>; | |
type TestConcatNumObjs = ConcatNumObjs<{ 0: 'a', 1: 'b' }, { 0: 'c', 1: 'd' }>; | |
export type TupleToUnion<R extends List<any>, I extends number = 0, Acc = never> = | |
{ 1: TupleToUnion<R, Inc[I], Acc | R[I]>, 0: Acc }[TupleHasIndex<R, I>]; | |
type Arr2UnionTest = TupleToUnion<TestArr>; | |
export type TupleIndicesToUnion<R extends List<any>, I extends number = 0, Acc = never> = | |
{ 1: TupleIndicesToUnion<R, Inc[I], Acc | I>, 0: Acc }[TupleHasIndex<R, I>]; | |
type ArrKeys2UnionTest = TupleIndicesToUnion<TestArr>; | |
export type LengthList<R extends List<any>> = R['length']; | |
type TestVectorLength = LengthList<{ 0: 'a', 1: 'b', length: 2 }>; | |
export type Length<R extends NumObj<any>, I extends number = 0> = | |
{ 1: Length<R, Inc[I]>, 0: I }[ObjectHasKey<R, I>]; | |
type TestObjLength = Length<TupleToObject<TestArr>>; | |
type TestTplLength = Length<TestArr>; | |
type TestArrLength = Length<any[]>; | |
type TestNumLength = Length<{ 0: 'a', 1: 'b' }>; | |
export type Vector<T, N extends number, I extends number = 0, Acc = { length: N }> = | |
{ 1: Acc, 0: Vector<T, N, Inc[I], Acc & { [P in NumberToString[I]]: T }> }[NumbersEqual<I, N>]; | |
type TestVector = Vector<number, 3>; | |
// export type TupleLastIndex<R extends {}> = Dec[Length<R>]; | |
export type TupleLastIndex<R extends List<any>, I extends number = 0> = | |
{ 1: TupleLastIndex<R, Inc[I]>, 0: Dec[I] }[TupleHasIndex<R, I>]; | |
type TestLast = TupleLastIndex<TestArr>; | |
type TestLastArr = TupleLastIndex<any[]>; | |
export type TupleLastElem<R extends List<any>, I extends number = 0> = | |
{ 1: TupleLastElem<R, Inc[I]>, 0: R[Dec[I]] }[TupleHasIndex<R, I>]; | |
type TestLastElem = TupleLastElem<TestArr>; | |
// v useless type to demo backward iteration | |
export type FirstElem<R extends List<any>, I extends number = Length<R>, Prev extends number = Dec[I]> = | |
{ 1: FirstElem<R, Prev>, 0: R[I] }[TupleHasIndex<R, Prev>]; | |
// ^ #15768, TS2536 `X cannot be used to index Y` on generic | |
type TestFirstElem = FirstElem<TestArr>; | |
// v useless type to demo backward iteration | |
export type FirstIndex<R extends List<any>, I extends number = TupleLastIndex<R>> = | |
{ 1: FirstIndex<R, Dec[I]>, 0: Inc[I] }[TupleHasIndex<R, I>]; | |
// ^ Generic type instantiation is excessively deep and possibly infinite | |
type TestFirstIndex = FirstIndex<TestArr>; | |
// ^ WRONG | |
// Ramda functions listed in #12512 redone with iteration: | |
export type PathFn<T, R extends List<string|number>, I extends number = 0> = | |
{ 1: PathFn<T[R[I]], R, Inc[I]>, 0: T }[TupleHasIndex<R, I>]; | |
type PathTest = PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', 1, 'd']>; // "e" | |
export declare function path<T, R extends List<string|number>>(obj: T, path: R): PathFn<T, R>; | |
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<T, Def, R extends List<string|number>, I extends number = 0> = | |
{ 1: If<HasKey<T, R[I]>, PathOrFn<T[R[I]], Def, R, Inc[I]>, Def>, 0: T }[TupleHasIndex<R, I>]; | |
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<R extends List<Obj<any>>, I extends number = 0, T = {}> = | |
{ 1: MergeAllFn<R, Inc[I], Overwrite<T, R[I]>>, 0: T }[TupleHasIndex<R, I>]; | |
type MergeAllTest = MergeAllFn<[{ a: 1, b: 2 }, { b: 3, c: 4 }, { d: 5 }]>; // { a: 1, b: 3, c: 4, d: 5 } | |
export type FromPairsFn<R extends List<[string|number, any]>, I extends number = 0, T = {}> = | |
{ 1: FromPairsFn<R, Inc[I], Overwrite<T, { [P in R[I][0]]: R[I][1] }>>, 0: T }[TupleHasIndex<R, I>]; | |
type FromPairsTest = FromPairsFn<[['a', 1], ['b', 2], ['c', 3], ['a', 5]]>; | |
// { a: 5, b: 2, c: 3 } | |
export type ZipObjectFn<R extends List<string>, R2 extends List<any>, I extends number = 0, T = {}> = | |
{ 1: ZipObjectFn<R, R2, Inc[I], Overwrite<T, { [P in R[I]]: R2[I] }>>, 0: T }[TupleHasIndex<R, I>]; | |
type ZipObjectTest = ZipObjectFn<['a', 'b', 'c'], [1, 2, 3]>; | |
// { a: 1, b: 2, c: 3 } | |
export type ListFrom< | |
R extends List<any>, | |
N extends number, | |
I extends number = N, | |
Acc extends List<any> = { length: Subtract<Length<R>, I> } | |
> = { 0: Acc, 1: ListFrom<R, N, Inc[I], Acc & { [P in NumberToString[Subtract<I, N>]]: R[I] }> }[TupleHasIndex<T, I>]; | |
type TestListFrom = ListFrom<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, 2>; | |
export type ListTo< | |
R extends List<any>, | |
N extends number, | |
I extends number = 0, | |
Acc extends List<any> = { length: N } | |
> = { 0: Acc, 1: ListTo<R, N, Inc[I], Acc & { [P in NumberToString[I]]: R[I] }> }[NumbersEqual<I, N>]; | |
type TestListTo = ListTo<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, 2>; | |
export type ListTail<R extends List<any>> = ListFrom<R, 1>; | |
type TestListTail = ListTail<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }>; | |
export type DifferenceLists<Big extends List<any>, Small extends List<any>> = ListFrom<Big, ListLength<Small>>; | |
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<T extends List<any>, I extends number, Acc extends List<any> = []> = | |
// { 0: Acc, 1: TupleFrom<T, Inc[I], [...Acc, T[I]]> }[TupleHasIndex<T, I>]; | |
// type TestTupleFrom = TupleFrom<['a', 'b', 'c', 'd'], 2>; | |
// export type TupleTo<T extends List<any>, To extends number, I extends number = 0, Acc extends List<any>=[]> = | |
// If<TupleHasIndex<T, I>, { 0: Acc; 1: TupleTo<T, To, Inc[I], [...Acc, T[I]]>; }[NumbersEqual<I, To>], T>; | |
// type TestTupleTo = TupleTo<['a', 'b', 'c', 'd'], 2>; | |
// export type TupleTail<R extends List<any>> = TupleFrom<R, 1>; | |
// type TestTupleTail = TupleTail<['a', 'b', 'c']>; | |
// export type DifferenceTuples<Big extends List<any>, Small extends List<any>> = TupleFrom<Big, Length<Small>>; | |
// 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<A extends number, B extends number> = ObjectHasKey<{ [P in NumberToString[A]]: 'hi' }, NumberToString[B]>; | |
export type NumbersEqual< | |
A extends number, | |
B extends number | |
> = DefinitelyYes<StringsEqual<NumberToString[A], NumberToString[B]>>; | |
// ^ #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<T> = Pick<T, keyof T>; | |
type abc = { a: 1, b: 2, foo: () => string, toString: () => string, toLocaleString: () => string } | |
type bcd = Omit<abc, "b">; | |
type bdd = Omit<abc, "toString">; | |
type ccd = Simplify<abc & { "b": never }>; | |
type ccg = Simplify<abc & { "b": any }>; | |
type crd = Simplify<abc & { "toString": never }>; | |
type crg = Simplify<abc & { "toString": any }>; | |
type cqd = Simplify<abc & { "foo": never }>; | |
type cqg = Simplify<abc & { "foo": any }>; | |
type dcd = Overwrite<abc, { "b": never }>; | |
type dcg = Overwrite<abc, { "b": any }>; | |
type dcf = Overwrite<abc, { "toString": never }>; | |
type dch = Overwrite<abc, { "toString": any }>; | |
type duf = Overwrite<abc, { "foo": never }>; | |
type duh = Overwrite<abc, { "foo": any }>; | |
type cdd = Simplify<abc & { "toString": never }>; | |
type bce = Omit<myArr, "length">; | |
type ItemA = { a: string, b: number, c: boolean, toString(): string }; | |
type KeyedItem1 = keyof ItemA | |
type DiffedItem1 = Diff<keyof ItemA, "a"> | |
type OmittedItem1 = Omit<ItemA, "a"> | |
// should be { b: number, c: boolean, toString(): string } | |
// is { b: number; c: boolean; } | |
type OmittedItem2 = keyof Omit<ItemA, "a"> | |
// "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<A, B, C>(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<T>(a: T): T; | |
declare function compose<V0, T1>(fn0: (x0: V0) => T1): (x0: V0) => T1; | |
declare function compose<V0, T1, T2>(fn1: (x: T1) => T2, fn0: (x: V0) => T1): (x: V0) => T2; | |
declare function pipe <V0, T1>(fn0: (x0: V0) => T1): (x0: V0) => T1; // arity 1: same as compose | |
declare function pipe <V0, T1, T2>(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<T> = Pick<T, keyof T>; | |
type ArrProto<T extends List<any>> = AddPrototype<T> & { | |
[Symbol.iterator]: () => IterableIterator<T[-1]>, | |
[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<typeof foo> = foo; | |
t3[2]; // error | |
var t1: [number, string] = <ArrProto<[1, "a"]>>[1, "a"]; | |
// ^ ok | |
// v make either of these error: | |
var t5a: [number, string] = [1, "a", "b"]; | |
var t5b: [number, string] = <ArrProto<[1, "a", "b"]>> [1, "a", "b"]; | |
var t5c: TupleToObject<[number, string]> = [1, "a", "b"]; | |
var t5d: TupleToObject<[number, string]> = <TupleToObject<[1, "a", "b"]>> [1, "a", "b"]; | |
var t5e: TupleToObject<[number, string]> = <ArrProto<[1, "a", "b"]>> [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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment