| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  | import { arrayReduce } from 'wherehows-web/utils/array'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Aliases the exclusion / diff conditional type that specifies that an object | 
					
						
							|  |  |  |  * contains properties from T, that are not in K | 
					
						
							| 
									
										
										
										
											2018-08-01 10:22:41 -07:00
										 |  |  |  * From T pick a set of properties that are not in K | 
					
						
							| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  |  * @alias | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | type Omit<T, K> = Pick<T, Exclude<keyof T, K>>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-08-01 10:22:41 -07:00
										 |  |  |  * Aliases a record with properties of type keyof T and null values | 
					
						
							|  |  |  |  * Make all values in T null | 
					
						
							|  |  |  |  * @template T type to nullify | 
					
						
							|  |  |  |  * @alias | 
					
						
							| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-08-01 10:22:41 -07:00
										 |  |  | type Nullify<T> = Record<keyof T, null>; | 
					
						
							| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-27 09:33:20 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Checks if a type is an object | 
					
						
							|  |  |  |  * @param {any} candidate the entity to check | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const isObject = (candidate: any): candidate is object => | 
					
						
							|  |  |  |   candidate && Object.prototype.toString.call(candidate) === '[object Object]'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Checks that an object has it own enumerable props | 
					
						
							| 
									
										
										
										
											2017-12-11 13:13:34 -08:00
										 |  |  |  * @param {any} object the object to the be tested | 
					
						
							| 
									
										
										
										
											2017-09-27 09:33:20 -07:00
										 |  |  |  * @return {boolean} true if enumerable keys are present | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-12-11 13:13:34 -08:00
										 |  |  | const hasEnumerableKeys = (object: any): boolean => isObject(object) && !!Object.keys(object).length; | 
					
						
							| 
									
										
										
										
											2017-09-27 09:33:20 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-26 01:30:43 -08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Non mutative object attribute deletion. Removes the specified keys from a copy of the object and returns the copy. | 
					
						
							|  |  |  |  * @template T the object type to drop keys from | 
					
						
							|  |  |  |  * @template K the keys to be dropped from the object | 
					
						
							| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  |  * @param {T} o | 
					
						
							|  |  |  |  * @param {Array<K extends keyof T>} droppedKeys | 
					
						
							|  |  |  |  * @return {Pick<T, Exclude<keyof T, K extends keyof T>>} | 
					
						
							| 
									
										
										
										
											2018-02-26 01:30:43 -08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  | const omit = <T, K extends keyof T>(o: T, droppedKeys: Array<K>): Omit<T, K> => { | 
					
						
							| 
									
										
										
										
											2018-02-26 01:30:43 -08:00
										 |  |  |   const partialResult = Object.assign({}, o); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  |   return arrayReduce((partial: T, key: K) => { | 
					
						
							| 
									
										
										
										
											2018-02-26 01:30:43 -08:00
										 |  |  |     delete partial[key]; | 
					
						
							|  |  |  |     return partial; | 
					
						
							| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  |   }, partialResult)(droppedKeys); | 
					
						
							| 
									
										
										
										
											2018-02-26 01:30:43 -08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Extracts keys from a source to a new object | 
					
						
							|  |  |  |  * @template T the object to select keys from | 
					
						
							|  |  |  |  * @param {T} o the source object | 
					
						
							|  |  |  |  * @param {Array<K extends keyof T>} pickedKeys | 
					
						
							|  |  |  |  * @return {Select<T extends object, K extends keyof T>} | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-08-01 10:22:41 -07:00
										 |  |  | const pick = <T, K extends keyof T>(o: T, pickedKeys: Array<K>): Pick<T, K> => | 
					
						
							| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  |   arrayReduce( | 
					
						
							| 
									
										
										
										
											2018-08-01 10:22:41 -07:00
										 |  |  |     (partial: T, key: K): Pick<T, K> => | 
					
						
							|  |  |  |       pickedKeys.includes(key) ? Object.assign(partial, { [key]: o[key] }) : partial, | 
					
						
							| 
									
										
										
										
											2018-07-31 13:31:57 -07:00
										 |  |  |     <T>{} | 
					
						
							|  |  |  |   )(pickedKeys); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-01 10:22:41 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Creates an object of type T with a set of properties of type null | 
					
						
							|  |  |  |  * @template T the type of the source object | 
					
						
							|  |  |  |  * @template K union of literal types of properties | 
					
						
							|  |  |  |  * @param {T} o instance of T to be set to null | 
					
						
							|  |  |  |  * @returns {Nullify<T>} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const nullify = <T, K extends keyof T>(o: T): Nullify<T> => { | 
					
						
							|  |  |  |   let nullObj = <Nullify<T>>{}; | 
					
						
							|  |  |  |   return arrayReduce((nullObj, key: K) => Object.assign(nullObj, { [key]: null }), nullObj)(<Array<K>>Object.keys(o)); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export { Omit, Nullify }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export { isObject, hasEnumerableKeys, omit, pick, nullify }; |