mapKeys
Map the key names of an object to new key names, supporting custom conversion functions.
Basic Usage
typescript
import { mapKeys } from 'radash'
const obj = { name: 'Alice', age: 25, city: 'Beijing' }
const mapped = mapKeys(obj, key => key.toUpperCase())
console.log(mapped) // { NAME: 'Alice', AGE: 25, CITY: 'Beijing' }
Syntax
typescript
function mapKeys<T extends Record<string, any>, U extends Record<string, any>>(
obj: T,
fn: (key: keyof T) => string
): U
Parameters
obj
(T): The object whose keys to mapfn
(function): The mapping function, receives the key name and returns the new key name
Return Value
Returns the new object after mapping, values remain unchanged.
Examples
Basic Key Mapping
typescript
import { mapKeys } from 'radash'
const obj = { name: 'Alice', age: 25, city: 'Beijing' }
// Convert keys to uppercase
const mapped1 = mapKeys(obj, key => key.toUpperCase())
console.log(mapped1) // { NAME: 'Alice', AGE: 25, CITY: 'Beijing' }
// Convert keys to lowercase
const mapped2 = mapKeys(obj, key => key.toLowerCase())
console.log(mapped2) // { name: 'Alice', age: 25, city: 'Beijing' }
Add Prefix and Suffix
typescript
import { mapKeys } from 'radash'
const obj = { name: 'Alice', age: 25, city: 'Beijing' }
// Add prefix
const mapped1 = mapKeys(obj, key => `user_${key}`)
console.log(mapped1) // { user_name: 'Alice', user_age: 25, user_city: 'Beijing' }
// Add suffix
const mapped2 = mapKeys(obj, key => `${key}_field`)
console.log(mapped2) // { name_field: 'Alice', age_field: 25, city_field: 'Beijing' }
// Add both prefix and suffix
const mapped3 = mapKeys(obj, key => `data_${key}_info`)
console.log(mapped3) // { data_name_info: 'Alice', data_age_info: 25, data_city_info: 'Beijing' }
Key Format Conversion
typescript
import { mapKeys } from 'radash'
const obj = { userName: 'Alice', emailAddress: 'alice@example.com', phoneNumber: '123-456-7890' }
// Convert to snake_case
const mapped1 = mapKeys(obj, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped1) // { user_name: 'Alice', email_address: 'alice@example.com', phone_number: '123-456-7890' }
// Convert to kebab-case
const mapped2 = mapKeys(obj, key => key.replace(/([A-Z])/g, '-$1').toLowerCase())
console.log(mapped2) // { user-name: 'Alice', email-address: 'alice@example.com', phone-number: '123-456-7890' }
// Convert to dot.case
const mapped3 = mapKeys(obj, key => key.replace(/([A-Z])/g, '.$1').toLowerCase())
console.log(mapped3) // { user.name: 'Alice', email.address: 'alice@example.com', phone.number: '123-456-7890' }
Handling Special Characters
typescript
import { mapKeys } from 'radash'
const obj = {
'user-name': 'Alice',
'email@domain': 'alice@example.com',
'phone_number': '123-456-7890',
'first.name': 'Alice',
'last name': 'Smith'
}
// Remove special characters
const mapped1 = mapKeys(obj, key => key.replace(/[^a-zA-Z0-9]/g, ''))
console.log(mapped1) // { username: 'Alice', emaildomain: 'alice@example.com', phonenumber: '123-456-7890', firstname: 'Alice', lastname: 'Smith' }
// Replace special characters with underscore
const mapped2 = mapKeys(obj, key => key.replace(/[^a-zA-Z0-9]/g, '_'))
console.log(mapped2) // { user_name: 'Alice', email_domain: 'alice@example.com', phone_number: '123-456-7890', first_name: 'Alice', last_name: 'Smith' }
Handling Numbers and Symbols
typescript
import { mapKeys } from 'radash'
const obj = {
'user123': 'Alice',
'api_v1': 'v1',
'test@123': 'test',
'hello-world': 'hello',
'user_name_123': 'user'
}
// Remove numbers
const mapped1 = mapKeys(obj, key => key.replace(/\d/g, ''))
console.log(mapped1) // { user: 'Alice', api_v: 'v1', test@: 'test', hello-world: 'hello', user_name_: 'user' }
// Keep only letters and numbers, remove others
const mapped2 = mapKeys(obj, key => key.replace(/[^a-zA-Z0-9]/g, ''))
console.log(mapped2) // { user123: 'Alice', apiv1: 'v1', test123: 'test', helloworld: 'hello', username123: 'user' }
Handling Nested Objects
typescript
import { mapKeys } from 'radash'
const obj = {
user: { name: 'Alice', age: 25 },
settings: { theme: 'dark', language: 'en' }
}
// Note: mapKeys only processes top-level keys, does not recursively process nested objects
const mapped = mapKeys(obj, key => `config_${key}`)
console.log(mapped)
// {
// config_user: { name: 'Alice', age: 25 },
// config_settings: { theme: 'dark', language: 'en' }
// }
Handling Array Values
typescript
import { mapKeys } from 'radash'
const obj = {
userNames: ['Alice', 'Bob', 'Charlie'],
emailAddresses: ['alice@example.com', 'bob@example.com'],
phoneNumbers: ['123-456-7890', '098-765-4321']
}
// Convert key format
const mapped = mapKeys(obj, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// user_names: ['Alice', 'Bob', 'Charlie'],
// email_addresses: ['alice@example.com', 'bob@example.com'],
// phone_numbers: ['123-456-7890', '098-765-4321']
// }
Handling Function Values
typescript
import { mapKeys } from 'radash'
const obj = {
userHandler: () => 'hello',
emailValidator: function() { return true },
phoneProcessor: (x: number) => x * 2
}
// Convert key format
const mapped = mapKeys(obj, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// user_handler: [Function: userHandler],
// email_validator: [Function: emailValidator],
// phone_processor: [Function: phoneProcessor]
// }
Handling Date Values
typescript
import { mapKeys } from 'radash'
const obj = {
createdAt: new Date('2023-01-01'),
updatedAt: new Date('2023-12-31'),
birthday: new Date('1998-05-15')
}
// Convert key format
const mapped = mapKeys(obj, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// created_at: 2023-01-01T00:00:00.000Z,
// updated_at: 2023-12-31T00:00:00.000Z,
// birthday: 1998-05-15T00:00:00.000Z
// }
Handling Boolean Values
typescript
import { mapKeys } from 'radash'
const obj = {
isActive: true,
isVerified: false,
isPremium: true,
isBlocked: false
}
// Convert key format
const mapped = mapKeys(obj, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// is_active: true,
// is_verified: false,
// is_premium: true,
// is_blocked: false
// }
Handling Number Values
typescript
import { mapKeys } from 'radash'
const obj = {
userID: 1,
userScore: 95.5,
userRating: 4.8,
userCount: 0,
userPrice: -10.99
}
// Convert key format
const mapped = mapKeys(obj, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// user_id: 1,
// user_score: 95.5,
// user_rating: 4.8,
// user_count: 0,
// user_price: -10.99
// }
Handling API Response Data
typescript
import { mapKeys } from 'radash'
const apiResponse = {
responseStatus: 200,
responseData: { id: 1, name: 'Alice' },
responseMeta: { timestamp: new Date(), requestId: 'req_123456' }
}
// Remove prefix and convert format
const mapped = mapKeys(apiResponse, key => {
const newKey = key.replace('response', '').toLowerCase()
return newKey.charAt(0).toLowerCase() + newKey.slice(1)
})
console.log(mapped)
// {
// status: 200,
// data: { id: 1, name: 'Alice' },
// meta: { timestamp: 2023-12-31T12:00:00.000Z, requestId: 'req_123456' }
// }
Handling Form Data
typescript
import { mapKeys } from 'radash'
const formData = {
personalInfo: {
firstName: 'Alice',
lastName: 'Smith',
emailAddress: 'alice@example.com'
},
addressInfo: {
streetAddress: '123 Main St',
cityName: 'Beijing',
countryCode: 'CN'
}
}
// Convert key format
const mapped = mapKeys(formData, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// personal_info: { firstName: 'Alice', lastName: 'Smith', emailAddress: 'alice@example.com' },
// address_info: { streetAddress: '123 Main St', cityName: 'Beijing', countryCode: 'CN' }
// }
Handling Config Objects
typescript
import { mapKeys } from 'radash'
const config = {
serverConfig: {
hostName: 'localhost',
portNumber: 3000,
enableSSL: true
},
databaseConfig: {
connectionURL: 'postgresql://localhost:5432/mydb',
poolSettings: { minConnections: 1, maxConnections: 10 }
},
apiConfig: {
versionNumber: 'v1',
rateLimitSettings: { windowMilliseconds: 900000, maxRequests: 100 }
}
}
// Convert key format
const mapped = mapKeys(config, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// server_config: { hostName: 'localhost', portNumber: 3000, enableSSL: true },
// database_config: { connectionURL: 'postgresql://localhost:5432/mydb', poolSettings: { minConnections: 1, maxConnections: 10 } },
// api_config: { versionNumber: 'v1', rateLimitSettings: { windowMilliseconds: 900000, maxRequests: 100 } }
// }
Handling Error Objects
typescript
import { mapKeys } from 'radash'
const errorObject = {
errorName: 'ValidationError',
errorMessage: 'Invalid input',
errorDetails: {
fieldName: 'email',
fieldValue: 'invalid-email',
validationConstraints: { format: 'Must be a valid email' }
}
}
// Remove prefix and convert format
const mapped = mapKeys(errorObject, key => {
const newKey = key.replace('error', '').toLowerCase()
return newKey.charAt(0).toLowerCase() + newKey.slice(1)
})
console.log(mapped)
// {
// name: 'ValidationError',
// message: 'Invalid input',
// details: { fieldName: 'email', fieldValue: 'invalid-email', validationConstraints: { format: 'Must be a valid email' } }
// }
Handling Log Data
typescript
import { mapKeys } from 'radash'
const logEntry = {
logTimestamp: new Date(),
logLevel: 'ERROR',
logMessage: 'Database connection failed',
logContext: { userId: 123, requestId: 'req_456' },
errorInfo: { errorCode: 'ECONNREFUSED', errorMessage: 'Connection refused' }
}
// Remove prefix and convert format
const mapped = mapKeys(logEntry, key => {
const newKey = key.replace('log', '').toLowerCase()
return newKey.charAt(0).toLowerCase() + newKey.slice(1)
})
console.log(mapped)
// {
// timestamp: 2023-12-31T12:00:00.000Z,
// level: 'ERROR',
// message: 'Database connection failed',
// context: { userId: 123, requestId: 'req_456' },
// errorInfo: { errorCode: 'ECONNREFUSED', errorMessage: 'Connection refused' }
// }
Handling Database Query Results
typescript
import { mapKeys } from 'radash'
const dbResult = {
recordID: 1,
productName: 'Product A',
categoryInfo: {
categoryID: 5,
categoryName: 'Electronics'
},
productVariants: [
{ variantID: 101, colorName: 'Red', priceValue: 99.99 },
{ variantID: 102, colorName: 'Blue', priceValue: 89.99 }
]
}
// Convert key format
const mapped = mapKeys(dbResult, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// record_id: 1,
// product_name: 'Product A',
// category_info: { categoryID: 5, categoryName: 'Electronics' },
// product_variants: [{ variantID: 101, colorName: 'Red', priceValue: 99.99 }, { variantID: 102, colorName: 'Blue', priceValue: 89.99 }]
// }
Handling Empty Objects and Edge Cases
typescript
import { mapKeys } from 'radash'
// Empty object
console.log(mapKeys({}, key => key)) // {}
// Only one key-value pair
console.log(mapKeys({ key: 'value' }, key => key.toUpperCase())) // { KEY: 'value' }
// Contains null values
console.log(mapKeys({ a: 1, b: null, c: undefined }, key => key.toUpperCase()))
// { A: 1, B: null, C: undefined }
Handling Complex Mapping Scenarios
typescript
import { mapKeys } from 'radash'
const complexObj = {
userProfile: {
personalInfo: {
fullName: 'Alice Smith',
ageValue: 25
},
userSettings: {
themePreference: 'dark',
notificationSettings: {
emailNotifications: true,
pushNotifications: false
}
}
},
systemInfo: {
versionNumber: '1.0.0',
environmentType: 'production'
}
}
// Convert key format
const mapped = mapKeys(complexObj, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// user_profile: { personalInfo: { fullName: 'Alice Smith', ageValue: 25 }, userSettings: { themePreference: 'dark', notificationSettings: { emailNotifications: true, pushNotifications: false } } },
// system_info: { versionNumber: '1.0.0', environmentType: 'production' }
// }
Handling Enum Mapping
typescript
import { mapKeys } from 'radash'
const statusMap = {
userStatusActive: 'ACTIVE',
userStatusInactive: 'INACTIVE',
userStatusPending: 'PENDING',
userStatusSuspended: 'SUSPENDED'
}
// Convert key format
const mapped = mapKeys(statusMap, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// user_status_active: 'ACTIVE',
// user_status_inactive: 'INACTIVE',
// user_status_pending: 'PENDING',
// user_status_suspended: 'SUSPENDED'
// }
Handling Color Mapping
typescript
import { mapKeys } from 'radash'
const colorMap = {
primaryColor: '#FF0000',
secondaryColor: '#00FF00',
accentColor: '#0000FF',
warningColor: '#FFFF00',
successColor: '#800080'
}
// Convert key format
const mapped = mapKeys(colorMap, key => key.replace(/([A-Z])/g, '_$1').toLowerCase())
console.log(mapped)
// {
// primary_color: '#FF0000',
// secondary_color: '#00FF00',
// accent_color: '#0000FF',
// warning_color: '#FFFF00',
// success_color: '#800080'
// }
Notes
- Mapping Function: The mapping function must return a string as the new key name
- Nested Objects: Only processes top-level keys, does not recursively process nested objects
- Array Values: Array values are kept as is
- Immutability: Returns a new object, does not modify the original object
- Type Safety: Supports TypeScript type inference
Differences from Other Methods
Object.keys()
: Gets all keys of an objectmapKeys()
: Maps key names and returns a new objectmapValues()
: Maps values and returns a new objectmapEntries()
: Maps key-value pairs and returns a new object
Practical Application Scenarios
- Data Standardization: Unify key name formats of objects
- API Adaptation: Adapt key name formats for different APIs
- Database Mapping: Map database field names
- Config Processing: Handle key name formats in configuration objects
- Data Transformation: Convert key name formats between different systems