Convert Object Values
Converts specified values in objects or arrays of objects between string and number types, supporting nested properties via dot notation.
Import
import { convertObjectValues } from 'nhb-toolbox';
Function Signatures
// Object version
function convertObjectValues<T extends GenericObject, C extends 'string' | 'number'>(
data: T,
options: { keys: DotNotationKey<T>[]; convertTo: C }
): C extends 'string' ? Stringified<T> : Numberified<T>
// Array version
function convertObjectValues<T extends GenericObject, C extends 'string' | 'number'>(
data: T[],
options: { keys: DotNotationKey<T>[]; convertTo: C }
): C extends 'string' ? Stringified<T>[] : Numberified<T>[]
Usage Examples
- Object Conversion
- Array Conversion
- Nested Objects
Convert to Numbers
const product = {
id: "123",
price: "99.99",
meta: { weight: "1.5" }
};
const result = convertObjectValues(product, {
keys: ['price', 'meta.weight'],
convertTo: 'number'
});
// Returns { id: "123", price: 99.99, meta: { weight: 1.5 } }
// Type: Numberified<typeof product>
Convert to Strings
const user = {
id: 456,
profile: { age: 30 }
};
convertObjectValues(user, {
keys: ['id', 'profile.age'],
convertTo: 'string'
});
// Returns { id: "456", profile: { age: "30" } }
// Type: Stringified<typeof user>
Convert Array to Numbers
const items = [
{ sku: "A100", price: "25" },
{ sku: "B200", price: "50" }
];
convertObjectValues(items, {
keys: ['price'],
convertTo: 'number'
});
// Returns [
// { sku: "A100", price: 25 },
// { sku: "B200", price: 50 }
// ]
// Type: Numberified<typeof items[0]>[]
Convert Array to Strings
const measurements = [
{ temp: 36.5, timestamp: 1234567890 },
{ temp: 37.0, timestamp: 1234567999 }
];
convertObjectValues(measurements, {
keys: ['temp', 'timestamp'],
convertTo: 'string'
});
// Returns [
// { temp: "36.5", timestamp: "1234567890" },
// { temp: "37.0", timestamp: "1234567999" }
// ]
// Type: Stringified<typeof measurements[0]>[]
Complex Nested Conversion
const order = {
id: "1001",
total: "199.99",
items: [
{ id: "1", price: "49.99" },
{ id: "2", price: "59.99" }
],
customer: {
id: 5001,
loyaltyPoints: "1000"
}
};
// Convert numbers throughout structure
convertObjectValues(order, {
keys: ['total', 'items.price', 'customer.loyaltyPoints'],
convertTo: 'number'
});
/* Returns:
{
id: "1001",
total: 199.99,
items: [
{ id: "1", price: 49.99 },
{ id: "2", price: 59.99 }
],
customer: {
id: 5001,
loyaltyPoints: 1000
}
}
*/
Behavior Details
- Dot Notation: Supports nested paths like
'user.profile.age'
- Type Safety: Maintains proper TypeScript types in return value
- Non-Destructive: Returns new object/array without modifying original
- Selective Conversion: Only converts specified fields
- Array Support: Works with arrays of objects
Limitations
- Circular References: May cause stack overflow for deeply nested objects and arrays
- Special Types: Dates, RegExp etc. are treated as regular objects
- Invalid Numbers: String values that can't convert to numbers are preserved
- Performance: Deep cloning may be slow for large structures
Recommended Use Cases
- API response normalization
- Form data processing
- Database record preparation
- Configuration transformation
- Data migration scripts
Type Definitions
// Result when converting to strings
type Stringified<T> = {
[K in keyof T]: T[K] extends (infer U)[] ? Stringified<U>[]
: T[K] extends object | null | undefined ? Stringified<T[K]>
: T[K] extends string | number ? string
: T[K]
};
// Result when converting to numbers
type Numberified<T> = {
[K in keyof T]: T[K] extends (infer U)[] ? Numberified<U>[]
: T[K] extends object | null | undefined ? Numberified<T[K]>
: T[K] extends string ? number
: T[K] extends number ? T[K]
: number
};
/** - Dot-notation keys for nested objects with `any` value (including optional properties, excluding advanced non-primitive types) */
export type DotNotationKey<T> =
T extends AdvancedTypes ? never
: T extends GenericObject ?
{
[K in keyof T & string]: NonNullable<T[K]> extends GenericObject ?
`${K}` | `${K}.${DotNotationKey<NonNullable<T[K]>>}`
: `${K}`;
}[keyof T & string]
: never;
/** Advanced non-primitive types */
export type AdvancedTypes =
| Array<unknown>
| File
| FileList
| Blob
| Date
| RegExp
| WeakMap<WeakKey, unknown>
| WeakSet<WeakKey>
| Map<unknown, unknown>
| Set<unknown>
| GenericFn
| VoidFunction
| AsyncFunction<unknown>
| Promise<unknown>
| Error
| EvalError
| RangeError
| ReferenceError
| SyntaxError
| TypeError
| URIError
| bigint
| symbol;