Skip to content

keys

获取对象的所有键名,返回一个数组。

基础用法

typescript
import { keys } from 'radash'

const user = {
  id: 1,
  name: 'Alice',
  email: 'alice@example.com'
}

console.log(keys(user)) // ['id', 'name', 'email']

语法

typescript
function keys<T extends Record<string, any>>(obj: T): (keyof T)[]

参数

  • obj (T): 要获取键名的对象

返回值

返回一个包含对象所有键名的数组。

示例

基本对象键名获取

typescript
import { keys } from 'radash'

const user = {
  id: 1,
  name: 'Alice',
  email: 'alice@example.com',
  age: 25
}

const keyNames = keys(user)
console.log(keyNames) // ['id', 'name', 'email', 'age']

空对象处理

typescript
import { keys } from 'radash'

console.log(keys({})) // []
console.log(keys({ a: 1 })) // ['a']

嵌套对象键名

typescript
import { keys } from 'radash'

const user = {
  id: 1,
  profile: {
    name: 'Alice',
    email: 'alice@example.com'
  },
  settings: {
    theme: 'dark',
    notifications: true
  }
}

const keyNames = keys(user)
console.log(keyNames) // ['id', 'profile', 'settings']

// 获取嵌套对象的键名
const profileKeys = keys(user.profile)
console.log(profileKeys) // ['name', 'email']

const settingsKeys = keys(user.settings)
console.log(settingsKeys) // ['theme', 'notifications']

处理不同类型的值

typescript
import { keys } from 'radash'

const mixedObject = {
  string: 'hello',
  number: 123,
  boolean: true,
  null: null,
  undefined: undefined,
  array: [1, 2, 3],
  object: { a: 1 },
  function: () => {}
}

const keyNames = keys(mixedObject)
console.log(keyNames) // ['string', 'number', 'boolean', 'null', 'undefined', 'array', 'object', 'function']

表单字段验证

typescript
import { keys } from 'radash'

function validateRequiredFields(data: Record<string, any>, requiredFields: string[]) {
  const dataKeys = keys(data)
  const missingFields = requiredFields.filter(field => !dataKeys.includes(field))
  
  return {
    isValid: missingFields.length === 0,
    missingFields
  }
}

const formData = {
  name: 'Alice',
  email: 'alice@example.com',
  age: 25
}

const requiredFields = ['name', 'email', 'phone']

const validation = validateRequiredFields(formData, requiredFields)
console.log(validation) // { isValid: false, missingFields: ['phone'] }

对象比较

typescript
import { keys } from 'radash'

function compareObjects(obj1: Record<string, any>, obj2: Record<string, any>) {
  const keys1 = keys(obj1)
  const keys2 = keys(obj2)
  
  const commonKeys = keys1.filter(key => keys2.includes(key))
  const uniqueToObj1 = keys1.filter(key => !keys2.includes(key))
  const uniqueToObj2 = keys2.filter(key => !keys1.includes(key))
  
  return {
    commonKeys,
    uniqueToObj1,
    uniqueToObj2,
    hasSameKeys: keys1.length === keys2.length && uniqueToObj1.length === 0
  }
}

const obj1 = { a: 1, b: 2, c: 3 }
const obj2 = { b: 2, c: 3, d: 4 }

const comparison = compareObjects(obj1, obj2)
console.log(comparison)
// {
//   commonKeys: ['b', 'c'],
//   uniqueToObj1: ['a'],
//   uniqueToObj2: ['d'],
//   hasSameKeys: false
// }

动态属性访问

typescript
import { keys } from 'radash'

function getObjectValues(obj: Record<string, any>, filter?: (key: string) => boolean) {
  const objectKeys = keys(obj)
  const filteredKeys = filter ? objectKeys.filter(filter) : objectKeys
  
  return filteredKeys.map(key => obj[key])
}

const user = {
  id: 1,
  name: 'Alice',
  email: 'alice@example.com',
  age: 25,
  isActive: true
}

// 获取所有值
const allValues = getObjectValues(user)
console.log(allValues) // [1, 'Alice', 'alice@example.com', 25, true]

// 获取字符串类型的值
const stringValues = getObjectValues(user, key => typeof user[key] === 'string')
console.log(stringValues) // ['Alice', 'alice@example.com']

// 获取数字类型的值
const numberValues = getObjectValues(user, key => typeof user[key] === 'number')
console.log(numberValues) // [1, 25]

配置对象处理

typescript
import { keys } from 'radash'

function validateConfig(config: Record<string, any>) {
  const configKeys = keys(config)
  const errors: string[] = []
  
  const requiredKeys = ['apiUrl', 'databaseUrl', 'port']
  const optionalKeys = ['timeout', 'retries', 'cache']
  
  // 检查必需字段
  for (const requiredKey of requiredKeys) {
    if (!configKeys.includes(requiredKey)) {
      errors.push(`Missing required field: ${requiredKey}`)
    }
  }
  
  // 检查未知字段
  const allValidKeys = [...requiredKeys, ...optionalKeys]
  const unknownKeys = configKeys.filter(key => !allValidKeys.includes(key))
  
  if (unknownKeys.length > 0) {
    errors.push(`Unknown fields: ${unknownKeys.join(', ')}`)
  }
  
  return {
    isValid: errors.length === 0,
    errors
  }
}

const config = {
  apiUrl: 'https://api.example.com',
  databaseUrl: 'postgresql://localhost:5432/mydb',
  port: 3000,
  timeout: 5000,
  unknownField: 'value'
}

const validation = validateConfig(config)
console.log(validation)
// {
//   isValid: false,
//   errors: ['Unknown fields: unknownField']
// }

对象转换

typescript
import { keys } from 'radash'

function transformObject(obj: Record<string, any>, transformer: (key: string, value: any) => any) {
  const objectKeys = keys(obj)
  const transformed: Record<string, any> = {}
  
  for (const key of objectKeys) {
    transformed[key] = transformer(key, obj[key])
  }
  
  return transformed
}

const user = {
  name: 'alice',
  email: 'alice@example.com',
  age: 25
}

// 转换键名为大写
const upperCaseKeys = transformObject(user, (key, value) => value)
console.log(upperCaseKeys) // { name: 'alice', email: 'alice@example.com', age: 25 }

// 转换值为大写(如果是字符串)
const upperCaseValues = transformObject(user, (key, value) => 
  typeof value === 'string' ? value.toUpperCase() : value
)
console.log(upperCaseValues) // { name: 'ALICE', email: 'ALICE@EXAMPLE.COM', age: 25 }

对象深度遍历

typescript
import { keys } from 'radash'

function getNestedKeys(obj: Record<string, any>, prefix = ''): string[] {
  const objectKeys = keys(obj)
  const nestedKeys: string[] = []
  
  for (const key of objectKeys) {
    const fullKey = prefix ? `${prefix}.${key}` : key
    nestedKeys.push(fullKey)
    
    if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
      nestedKeys.push(...getNestedKeys(obj[key], fullKey))
    }
  }
  
  return nestedKeys
}

const nestedObject = {
  user: {
    profile: {
      name: 'Alice',
      email: 'alice@example.com'
    },
    settings: {
      theme: 'dark'
    }
  },
  config: {
    api: {
      url: 'https://api.example.com'
    }
  }
}

const nestedKeys = getNestedKeys(nestedObject)
console.log(nestedKeys)
// [
//   'user',
//   'user.profile',
//   'user.profile.name',
//   'user.profile.email',
//   'user.settings',
//   'user.settings.theme',
//   'config',
//   'config.api',
//   'config.api.url'
// ]

对象统计

typescript
import { keys } from 'radash'

function analyzeObject(obj: Record<string, any>) {
  const objectKeys = keys(obj)
  
  const analysis = {
    totalKeys: objectKeys.length,
    keyTypes: objectKeys.reduce((acc, key) => {
      const type = typeof obj[key]
      acc[type] = (acc[type] || 0) + 1
      return acc
    }, {} as Record<string, number>),
    keyNames: objectKeys,
    hasNestedObjects: objectKeys.some(key => 
      typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])
    )
  }
  
  return analysis
}

const complexObject = {
  id: 1,
  name: 'Alice',
  email: 'alice@example.com',
  isActive: true,
  profile: {
    age: 25,
    city: 'Beijing'
  },
  tags: ['developer', 'frontend'],
  lastLogin: null
}

const analysis = analyzeObject(complexObject)
console.log(analysis)
// {
//   totalKeys: 7,
//   keyTypes: { number: 1, string: 2, boolean: 1, object: 1, array: 1, object: 1 },
//   keyNames: ['id', 'name', 'email', 'isActive', 'profile', 'tags', 'lastLogin'],
//   hasNestedObjects: true
// }

对象序列化

typescript
import { keys } from 'radash'

function serializeObject(obj: Record<string, any>): string {
  const objectKeys = keys(obj)
  const pairs = objectKeys.map(key => `${key}=${encodeURIComponent(String(obj[key]))}`)
  return pairs.join('&')
}

const user = {
  name: 'Alice Smith',
  email: 'alice@example.com',
  age: 25,
  isActive: true
}

const serialized = serializeObject(user)
console.log(serialized) // 'name=Alice%20Smith&email=alice%40example.com&age=25&isActive=true'

对象过滤

typescript
import { keys } from 'radash'

function filterObject(obj: Record<string, any>, predicate: (key: string, value: any) => boolean) {
  const objectKeys = keys(obj)
  const filtered: Record<string, any> = {}
  
  for (const key of objectKeys) {
    if (predicate(key, obj[key])) {
      filtered[key] = obj[key]
    }
  }
  
  return filtered
}

const user = {
  id: 1,
  name: 'Alice',
  email: 'alice@example.com',
  age: 25,
  isActive: true,
  lastLogin: null
}

// 过滤掉空值
const nonNullValues = filterObject(user, (key, value) => value !== null && value !== undefined)
console.log(nonNullValues) // { id: 1, name: 'Alice', email: 'alice@example.com', age: 25, isActive: true }

// 过滤字符串类型的值
const stringValues = filterObject(user, (key, value) => typeof value === 'string')
console.log(stringValues) // { name: 'Alice', email: 'alice@example.com' }

注意事项

  1. 键名顺序: 返回的键名顺序与对象定义顺序一致
  2. 继承属性: 只返回对象自身的可枚举属性
  3. Symbol键: 不包含Symbol类型的键名
  4. 性能: 对于大型对象,性能良好
  5. 类型安全: 提供完整的TypeScript类型支持

与其他方法的区别

  • Object.keys(): 原生方法,功能相同
  • keys(): radash提供的键名获取方法
  • Object.getOwnPropertyNames(): 包含不可枚举属性
  • Reflect.ownKeys(): 包含Symbol键

实际应用场景

  1. 表单验证: 检查必需字段是否存在
  2. 对象比较: 比较两个对象的键名差异
  3. 动态属性访问: 根据键名动态访问对象属性
  4. 对象转换: 批量处理对象属性
  5. 配置管理: 验证配置对象的完整性

Released under the MIT License.