|
1 | 1 | import { MapLeafNodes } from './types'; |
2 | 2 |
|
3 | | -export function walkObject<T, MapTo>( |
| 3 | +type Primitive = string | number | null | undefined; |
| 4 | + |
| 5 | +type Walkable = { |
| 6 | + [Key in string | number]: Primitive | Walkable; |
| 7 | +}; |
| 8 | + |
| 9 | +export function walkObject<T extends Walkable, MapTo>( |
4 | 10 | obj: T, |
5 | | - fn: (value: string | number, path: Array<string>) => MapTo, |
| 11 | + fn: (value: Primitive, path: Array<string>) => MapTo, |
6 | 12 | path: Array<string> = [], |
7 | 13 | ): MapLeafNodes<T, MapTo> { |
8 | | - // @ts-expect-error |
9 | 14 | const clone = obj.constructor(); |
10 | 15 |
|
11 | 16 | for (let key in obj) { |
12 | 17 | const value = obj[key]; |
13 | 18 | const currentPath = [...path, key]; |
14 | 19 |
|
15 | | - if (typeof value === 'object') { |
16 | | - clone[key] = value ? walkObject(value, fn, currentPath) : value; |
17 | | - } else if (typeof value === 'string' || typeof value === 'number') { |
18 | | - clone[key] = fn(value, currentPath); |
| 20 | + if ( |
| 21 | + typeof value === 'string' || |
| 22 | + typeof value === 'number' || |
| 23 | + value == null |
| 24 | + ) { |
| 25 | + clone[key] = fn(value as Primitive, currentPath); |
| 26 | + } else if (typeof value === 'object' && !Array.isArray(value)) { |
| 27 | + clone[key] = walkObject(value as Walkable, fn, currentPath); |
19 | 28 | } else { |
20 | 29 | console.warn( |
21 | 30 | `Skipping invalid key "${currentPath.join( |
22 | 31 | '.', |
23 | | - )}". Should be a string, number or object. Received: "${typeof value}"`, |
| 32 | + )}". Should be a string, number, null or object. Received: "${ |
| 33 | + Array.isArray(value) ? 'Array' : typeof value |
| 34 | + }"`, |
24 | 35 | ); |
25 | 36 | } |
26 | 37 | } |
|
0 commit comments