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.