Skip to content

mapEntries

Map the key-value pairs of an object to new key-value pairs, supporting custom transformation functions.

Basic Usage

typescript
import { mapEntries } from 'radash'

const obj = { name: 'Alice', age: 25, city: 'Beijing' }
const mapped = mapEntries(obj, (key, value) => [key.toUpperCase(), value])
console.log(mapped) // { NAME: 'Alice', AGE: 25, CITY: 'Beijing' }

Syntax

typescript
function mapEntries<T extends Record<string, any>, U extends Record<string, any>>(
  obj: T,
  fn: (key: keyof T, value: T[keyof T]) => [string, any]
): U

Parameters

  • obj (T): The object to map
  • fn (function): The mapping function, receives key and value, returns a new [key, value] array

Return Value

Returns the new object after mapping.

Examples

Basic Key-Value Mapping

typescript
import { mapEntries } from 'radash'

const obj = { name: 'Alice', age: 25, city: 'Beijing' }

// Convert keys to uppercase
const mapped1 = mapEntries(obj, (key, value) => [key.toUpperCase(), value])
console.log(mapped1) // { NAME: 'Alice', AGE: 25, CITY: 'Beijing' }

// Convert keys to lowercase
const mapped2 = mapEntries(obj, (key, value) => [key.toLowerCase(), value])
console.log(mapped2) // { name: 'Alice', age: 25, city: 'Beijing' }

Custom Key-Value Transformation

typescript
import { mapEntries } from 'radash'

const obj = { name: 'Alice', age: 25, city: 'Beijing' }

// Add prefix to key names
const mapped1 = mapEntries(obj, (key, value) => [`user_${key}`, value])
console.log(mapped1) // { user_name: 'Alice', user_age: 25, user_city: 'Beijing' }

// Convert values to string
const mapped2 = mapEntries(obj, (key, value) => [key, String(value)])
console.log(mapped2) // { name: 'Alice', age: '25', city: 'Beijing' }

// Convert both key and value
const mapped3 = mapEntries(obj, (key, value) => [
  key.toUpperCase(),
  typeof value === 'string' ? value.toUpperCase() : value
])
console.log(mapped3) // { NAME: 'ALICE', AGE: 25, CITY: 'BEIJING' }

Handling Different Value Types

typescript
import { mapEntries } from 'radash'

const obj = {
  name: 'Alice',
  age: 25,
  isActive: true,
  score: 95.5,
  tags: ['admin', 'user']
}

// Handle different value types
const mapped = mapEntries(obj, (key, value) => {
  if (typeof value === 'string') {
    return [`${key}_str`, value.toUpperCase()]
  } else if (typeof value === 'number') {
    return [`${key}_num`, value * 2]
  } else if (typeof value === 'boolean') {
    return [`${key}_bool`, value ? 'YES' : 'NO']
  } else if (Array.isArray(value)) {
    return [`${key}_arr`, value.join(', ')]
  }
  return [key, value]
})

console.log(mapped)
// {
//   name_str: 'ALICE',
//   age_num: 50,
//   isActive_bool: 'YES',
//   score_num: 191,
//   tags_arr: 'admin, user'
// }

Handling Null and Undefined

typescript
import { mapEntries } from 'radash'

const obj = {
  name: 'Alice',
  email: null,
  phone: undefined,
  address: ''
}

// Filter out null values and convert key names
const mapped = mapEntries(obj, (key, value) => {
  if (value == null) {
    return [`${key}_null`, 'N/A']
  }
  return [key, value]
})

console.log(mapped)
// {
//   name: 'Alice',
//   email_null: 'N/A',
//   phone_null: 'N/A',
//   address: ''
// }

Handling Nested Objects

typescript
import { mapEntries } from 'radash'

const obj = {
  user: { name: 'Alice', age: 25 },
  settings: { theme: 'dark', language: 'en' }
}

// Flatten nested objects
const mapped = mapEntries(obj, (key, value) => {
  if (typeof value === 'object' && value !== null) {
    return Object.entries(value).map(([subKey, subValue]) => [
      `${key}_${subKey}`,
      subValue
    ])
  }
  return [key, value]
})

console.log(mapped)
// {
//   user_name: 'Alice',
//   user_age: 25,
//   settings_theme: 'dark',
//   settings_language: 'en'
// }

Handling Function Values

typescript
import { mapEntries } from 'radash'

const obj = {
  name: 'Alice',
  handler: () => 'hello',
  validator: function() { return true },
  processor: (x: number) => x * 2
}

// Convert function to string description
const mapped = mapEntries(obj, (key, value) => {
  if (typeof value === 'function') {
    return [`${key}_fn`, value.toString()]
  }
  return [key, value]
})

console.log(mapped)
// {
//   name: 'Alice',
//   handler_fn: '() => \'hello\'',
//   validator_fn: 'function() { return true }',
//   processor_fn: '(x) => x * 2'
// }

Handling Date Values

typescript
import { mapEntries } from 'radash'

const obj = {
  createdAt: new Date('2023-01-01'),
  updatedAt: new Date('2023-12-31'),
  birthday: new Date('1998-05-15')
}

// Convert date to ISO string
const mapped = mapEntries(obj, (key, value) => {
  if (value instanceof Date) {
    return [`${key}_iso`, value.toISOString()]
  }
  return [key, value]
})

console.log(mapped)
// {
//   createdAt_iso: '2023-01-01T00:00:00.000Z',
//   updatedAt_iso: '2023-12-31T00:00:00.000Z',
//   birthday_iso: '1998-05-15T00:00:00.000Z'
// }

Handling Boolean Values

typescript
import { mapEntries } from 'radash'

const obj = {
  isActive: true,
  isVerified: false,
  isPremium: true,
  isBlocked: false
}

// Convert boolean to string
const mapped = mapEntries(obj, (key, value) => {
  if (typeof value === 'boolean') {
    return [`${key}_str`, value ? 'YES' : 'NO']
  }
  return [key, value]
})

console.log(mapped)
// {
//   isActive_str: 'YES',
//   isVerified_str: 'NO',
//   isPremium_str: 'YES',
//   isBlocked_str: 'NO'
// }

Handling Number Values

typescript
import { mapEntries } from 'radash'

const obj = {
  id: 1,
  score: 95.5,
  rating: 4.8,
  count: 0,
  price: -10.99
}

// Convert number to different format
const mapped = mapEntries(obj, (key, value) => {
  if (typeof value === 'number') {
    return [
      `${key}_formatted`,
      value < 0 ? `(${Math.abs(value)})` : value.toString()
    ]
  }
  return [key, value]
})

console.log(mapped)
// {
//   id_formatted: '1',
//   score_formatted: '95.5',
//   rating_formatted: '4.8',
//   count_formatted: '0',
//   price_formatted: '(10.99)'
// }

Handling API Response Data

typescript
import { mapEntries } from 'radash'

const apiResponse = {
  status: 200,
  data: { id: 1, name: 'Alice' },
  meta: { timestamp: new Date(), requestId: 'req_123456' }
}

// Add prefix and convert value
const mapped = mapEntries(apiResponse, (key, value) => {
  const newKey = `api_${key}`
  if (key === 'status') {
    return [newKey, value === 200 ? 'SUCCESS' : 'ERROR']
  }
  if (key === 'data') {
    return [newKey, JSON.stringify(value)]
  }
  if (key === 'meta') {
    return [newKey, value.timestamp.toISOString()]
  }
  return [newKey, value]
})

console.log(mapped)
// {
//   api_status: 'SUCCESS',
//   api_data: '{"id":1,"name":"Alice"}',
//   api_meta: '2023-12-31T12:00:00.000Z'
// }

Handling Form Data

typescript
import { mapEntries } from 'radash'

const formData = {
  personal: {
    firstName: 'Alice',
    lastName: 'Smith',
    email: 'alice@example.com'
  },
  address: {
    street: '123 Main St',
    city: 'Beijing',
    country: 'China'
  }
}

// Flatten form data
const mapped = mapEntries(formData, (key, value) => {
  if (typeof value === 'object' && value !== null) {
    return Object.entries(value).map(([subKey, subValue]) => [
      `${key}_${subKey}`,
      subValue
    ])
  }
  return [key, value]
})

console.log(mapped)
// {
//   personal_firstName: 'Alice',
//   personal_lastName: 'Smith',
//   personal_email: 'alice@example.com',
//   address_street: '123 Main St',
//   address_city: 'Beijing',
//   address_country: 'China'
// }

Handling Error Objects

typescript
import { mapEntries } from 'radash'

const errorObject = {
  name: 'ValidationError',
  message: 'Invalid input',
  details: {
    field: 'email',
    value: 'invalid-email',
    constraints: { format: 'Must be a valid email' }
  }
}

// Convert error object to log format
const mapped = mapEntries(errorObject, (key, value) => {
  const newKey = `error_${key}`
  if (key === 'details') {
    return [newKey, JSON.stringify(value)]
  }
  return [newKey, value]
})

console.log(mapped)
// {
//   error_name: 'ValidationError',
//   error_message: 'Invalid input',
//   error_details: '{"field":"email","value":"invalid-email","constraints":{"format":"Must be a valid email"}}'
// }

Handling Log Data

typescript
import { mapEntries } from 'radash'

const logEntry = {
  timestamp: new Date(),
  level: 'ERROR',
  message: 'Database connection failed',
  context: { userId: 123, requestId: 'req_456' },
  error: { code: 'ECONNREFUSED', message: 'Connection refused' }
}

// Convert log data to structured format
const mapped = mapEntries(logEntry, (key, value) => {
  const newKey = `log_${key}`
  if (value instanceof Date) {
    return [newKey, value.toISOString()]
  }
  if (typeof value === 'object' && value !== null) {
    return [newKey, JSON.stringify(value)]
  }
  return [newKey, value]
})

console.log(mapped)
// {
//   log_timestamp: '2023-12-31T12:00:00.000Z',
//   log_level: 'ERROR',
//   log_message: 'Database connection failed',
//   log_context: '{"userId":123,"requestId":"req_456"}',
//   log_error: '{"code":"ECONNREFUSED","message":"Connection refused"}'
// }

Handling Database Query Results

typescript
import { mapEntries } from 'radash'

const dbResult = {
  id: 1,
  name: 'Product A',
  category: {
    id: 5,
    name: 'Electronics'
  },
  variants: [
    { id: 101, color: 'Red', price: 99.99 },
    { id: 102, color: 'Blue', price: 89.99 }
  ]
}

// Convert database result to API format
const mapped = mapEntries(dbResult, (key, value) => {
  const newKey = `db_${key}`
  if (key === 'category') {
    return [newKey, JSON.stringify(value)]
  }
  if (key === 'variants') {
    return [newKey, value.length.toString()]
  }
  return [newKey, value]
})

console.log(mapped)
// {
//   db_id: 1,
//   db_name: 'Product A',
//   db_category: '{"id":5,"name":"Electronics"}',
//   db_variants: '2'
// }

Handling Config Objects

typescript
import { mapEntries } from 'radash'

const config = {
  server: {
    host: 'localhost',
    port: 3000
  },
  database: {
    url: 'postgresql://localhost:5432/mydb',
    pool: { min: 1, max: 10 }
  },
  api: {
    version: 'v1',
    rateLimit: { windowMs: 900000, max: 100 }
  }
}

// Flatten config object
const mapped = mapEntries(config, (key, value) => {
  if (typeof value === 'object' && value !== null) {
    return Object.entries(value).map(([subKey, subValue]) => [
      `${key}_${subKey}`,
      subValue
    ])
  }
  return [key, value]
})

console.log(mapped)
// {
//   server_host: 'localhost',
//   server_port: 3000,
//   database_url: 'postgresql://localhost:5432/mydb',
//   database_pool: { min: 1, max: 10 },
//   api_version: 'v1',
//   api_rateLimit: { windowMs: 900000, max: 100 }
// }

Handling Empty Objects and Edge Cases

typescript
import { mapEntries } from 'radash'

// Empty object
console.log(mapEntries({}, (key, value) => [key, value])) // {}

// Only one key-value pair
console.log(mapEntries({ key: 'value' }, (key, value) => [key.toUpperCase(), value]))
// { KEY: 'value' }

// Contains null values
console.log(mapEntries({ a: 1, b: null, c: undefined }, (key, value) => [
  key,
  value ?? 'default'
]))
// { a: 1, b: 'default', c: 'default' }

Handling Complex Mapping Scenarios

typescript
import { mapEntries } from 'radash'

const complexObj = {
  user: {
    profile: {
      name: 'Alice',
      age: 25
    },
    settings: {
      theme: 'dark',
      language: 'en'
    }
  },
  system: {
    version: '1.0.0',
    environment: 'production'
  }
}

// Deep flatten complex object
const mapped = mapEntries(complexObj, (key, value) => {
  const flatten = (obj: any, prefix = ''): [string, any][] => {
    return Object.entries(obj).flatMap(([k, v]) => {
      const newKey = prefix ? `${prefix}_${k}` : k
      if (typeof v === 'object' && v !== null && !Array.isArray(v)) {
        return flatten(v, newKey)
      }
      return [[newKey, v]]
    })
  }

  if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
    return flatten(value, key)
  }
  return [key, value]
})

console.log(mapped)
// {
//   user_profile_name: 'Alice',
//   user_profile_age: 25,
//   user_settings_theme: 'dark',
//   user_settings_language: 'en',
//   system_version: '1.0.0',
//   system_environment: 'production'
// }

Notes

  1. Mapping Function: The mapping function must return an array in the format [string, any]
  2. Nested Objects: You need to manually handle mapping for nested objects
  3. Array Values: Array values are kept as is, special handling may be needed
  4. Immutability: Returns a new object, does not modify the original object
  5. Type Safety: Supports TypeScript type inference

Differences from Other Methods

  • Object.entries(): Gets an array of key-value pairs
  • mapEntries(): Maps key-value pairs and returns a new object
  • mapKeys(): Only maps key names
  • mapValues(): Only maps values

Practical Application Scenarios

  1. Data Transformation: Convert data formats between different systems
  2. API Adaptation: Adapt data formats for different APIs
  3. Config Processing: Transform configuration object structures
  4. Log Formatting: Format log data structures
  5. Database Mapping: Map database field names and values

Released under the MIT License.