@@ -31,13 +31,15 @@ const _hasOwn = Object.prototype.hasOwnProperty;
3131 * @returns {T }
3232 * @template T
3333 */
34- export function map < T > ( opt_initial : T | undefined ) {
35- const obj = Object . create ( null ) ;
34+ export const map = < T > ( opt_initial : T | null | undefined ) : object => {
35+ const object = Object . create ( null ) ;
3636 if ( opt_initial ) {
37- Object . assign ( obj , opt_initial ) ;
37+ Object . assign ( object , opt_initial ) ;
3838 }
39- return obj ;
40- }
39+
40+ // FIXME(@DerekNonGeneric): Should we be creating objects w/ null protos?
41+ return { ...opt_initial } ;
42+ } ;
4143
4244/**
4345 * Checks if the given key is a property in the map.
@@ -46,9 +48,9 @@ export function map<T>(opt_initial: T | undefined) {
4648 * @returns {boolean }
4749 * @template T
4850 */
49- export function hasOwn < T > ( obj : T , key : string ) {
50- return _hasOwn . call ( obj , key ) ;
51- }
51+ export const hasOwn = < T > ( object : T , key : string ) : boolean => {
52+ return _hasOwn . call ( object , key ) ;
53+ } ;
5254
5355/**
5456 * Returns obj[key] iff key is obj's own property (is not inherited).
@@ -57,42 +59,47 @@ export function hasOwn<T>(obj: T, key: string) {
5759 * @param {string } key
5860 * @returns {unknown }
5961 */
60- export function ownProperty ( obj : Record < string , number | RegExp > , key : string ) {
61- if ( hasOwn ( obj , key ) ) {
62- return obj [ key ] ;
63- } else {
64- return undefined ;
65- }
66- }
62+ export const ownProperty = (
63+ object : Record < string , number | RegExp > ,
64+ key : string
65+ ) : unknown => {
66+ return hasOwn ( object , key ) ? Reflect . get ( object , key ) : undefined ;
67+ } ;
6768
68- interface ITargetSourceDepth {
69- t : Object ;
70- s : Object ;
69+ /** @typedef {{t: object, s: object, d: number} } DeepMergeTuple */
70+ type DeepMergeTuple = {
71+ t : object ;
72+ s : object ;
7173 d : number ;
72- }
74+ } ;
7375
7476/**
7577 * Deep merges source into target.
7678 *
77- * @param {!Object } target
78- * @param {!Object } source
79- * @param {number } depth The maximum merge depth. If exceeded, Object.assign
80- * will be used instead.
81- * @returns {!Object }
79+ * @param {!object } target
80+ * @param {!object } source
81+ * @param {! number } depth The maximum merge depth. If exceeded, ` Object.assign`
82+ * will be used instead.
83+ * @return {!object }
8284 * @throws {Error } If source contains a circular reference.
8385 * Note: Only nested objects are deep-merged, primitives and arrays are not.
8486 */
85- export function deepMerge ( target : Object , source : Object , depth = 10 ) : Object {
87+ export const deepMerge = (
88+ target : object ,
89+ source : object ,
90+ depth = 10
91+ ) : object => {
8692 // Keep track of seen objects to detect recursive references.
87- const seen : Array < Object > = [ ] ;
93+ /** @type {!object[] } */
94+ const seen : object [ ] = [ ] ;
8895
89- /** @type {!Array<ITargetSourceDepth> } */
90- const queue : Array < ITargetSourceDepth > = [ ] ;
96+ /** @type {!DeepMergeTuple[] } */
97+ const queue : DeepMergeTuple [ ] = [ ] ;
9198 queue . push ( { t : target , s : source , d : 0 } ) ;
9299
93100 // BFS to ensure objects don't have recursive references at shallower depths.
94101 while ( queue . length > 0 ) {
95- const { t, s, d } = map ( queue . shift ( ) ) ;
102+ const { t, s, d } = /** @type { !DeepMergeTuple } */ Object ( queue . shift ( ) ) ;
96103 if ( seen . includes ( s ) ) {
97104 throw new Error ( 'Source object has a circular reference.' ) ;
98105 }
@@ -104,33 +111,33 @@ export function deepMerge(target: Object, source: Object, depth = 10): Object {
104111 Object . assign ( t , s ) ;
105112 continue ;
106113 }
107- Object . keys ( s ) . forEach ( ( key ) => {
108- const newValue = s [ key ] ;
114+ for ( const key of Object . keys ( s ) ) {
115+ const newValue = Reflect . get ( s , key ) ;
109116 // Perform a deep merge IFF both target and source have the same key
110117 // whose corresponding values are objects.
111118 if ( hasOwn ( t , key ) ) {
112- const oldValue = t [ key ] ;
119+ const oldValue = Reflect . get ( t , key ) ;
113120 if ( isObject ( newValue ) && isObject ( oldValue ) ) {
114121 queue . push ( { t : oldValue , s : newValue , d : d + 1 } ) ;
115- return ;
122+ continue ;
116123 }
117124 }
118- t [ key ] = newValue ;
119- } ) ;
125+ Reflect . set ( t , key , newValue ) ;
126+ }
120127 }
121128 return target ;
122- }
129+ } ;
123130
124131/**
125132 * @param {!Record<string, number | RegExp> | null | undefined } o1
126133 * @param {!Record<string, number | RegExp> | null | undefined } o2
127134 * @returns {boolean }
128135 */
129- export function objectsEqualShallow (
136+ export const objectsEqualShallow = (
130137 o1 : Record < string , number | RegExp > | null | undefined ,
131138 o2 : Record < string , number | RegExp > | null | undefined
132- ) : boolean {
133- if ( o1 === null || o2 === null ) {
139+ ) : boolean => {
140+ if ( o1 == undefined || o2 == undefined ) {
134141 // Null is only equal to null, and undefined to undefined.
135142 return o1 === o2 ;
136143 }
@@ -145,29 +152,29 @@ export function objectsEqualShallow(
145152 }
146153 }
147154 return true ;
148- }
155+ } ;
149156
150157/**
151158 * Takes an object, a property name, and a factory function. If the value of
152159 * the property is undefined, it generates a value with the factory function,
153160 * updates the object originally passed, and returns the value that was returned
154161 * by the factory function.
155162 *
156- * @param {T } obj
157- * @param {string } prop
163+ * @param {T extends object } object
164+ * @param {string } property
158165 * @param {function(T, string):R } factory
159166 * @returns {R }
160- * @template T,R
167+ * @template P, T,R
161168 */
162- export function memo < T , P extends keyof T > (
163- obj : T ,
164- prop : P ,
165- factory : ( arg0 : T , arg1 : P ) => T [ P ]
166- ) : T [ P ] {
167- let result = obj [ prop ] ;
169+ export const memo = < T extends object , P extends keyof T > (
170+ object : T ,
171+ property : P ,
172+ factory : ( argument0 : T , argument1 : P ) => T [ P ]
173+ ) : T [ P ] => {
174+ let result = Reflect . get ( object , property ) ;
168175 if ( result === undefined ) {
169- result = factory ( obj , prop ) ;
170- obj [ prop ] = result ;
176+ result = factory ( object , property ) ;
177+ Reflect . set ( object , property , result ) ;
171178 }
172179 return result ;
173- }
180+ } ;
0 commit comments