Skip to content

isPrimitive

检查一个值是否为原始类型(primitive type)。

基础用法

typescript
import { isPrimitive } from 'radash'

console.log(isPrimitive('hello'))          // true
console.log(isPrimitive(123))              // true
console.log(isPrimitive(true))             // true
console.log(isPrimitive(null))             // true
console.log(isPrimitive(undefined))        // true
console.log(isPrimitive(Symbol('test')))   // true
console.log(isPrimitive({}))               // false
console.log(isPrimitive([]))               // false
console.log(isPrimitive(() => {}))         // false

语法

typescript
function isPrimitive(value: any): value is string | number | boolean | null | undefined | symbol

参数

  • value (any): 要检查的值

返回值

返回一个布尔值,如果值是原始类型则返回 true,否则返回 false。同时作为TypeScript类型守卫。

示例

基本类型检查

typescript
import { isPrimitive } from 'radash'

// 字符串
console.log(isPrimitive('hello'))          // true
console.log(isPrimitive(''))               // true
console.log(isPrimitive('123'))            // true

// 数字
console.log(isPrimitive(123))              // true
console.log(isPrimitive(0))                // true
console.log(isPrimitive(-10))              // true
console.log(isPrimitive(3.14))             // true
console.log(isPrimitive(Infinity))         // true
console.log(isPrimitive(-Infinity))        // true
console.log(isPrimitive(NaN))              // true

// 布尔值
console.log(isPrimitive(true))             // true
console.log(isPrimitive(false))            // true

// null 和 undefined
console.log(isPrimitive(null))             // true
console.log(isPrimitive(undefined))        // true

// Symbol
console.log(isPrimitive(Symbol('test')))   // true
console.log(isPrimitive(Symbol()))         // true

// 非原始类型
console.log(isPrimitive({}))               // false
console.log(isPrimitive([]))               // false
console.log(isPrimitive(() => {}))         // false
console.log(isPrimitive(new Date()))       // false
console.log(isPrimitive(new RegExp('')))   // false

包装对象检查

typescript
import { isPrimitive } from 'radash'

// 包装对象不是原始类型
console.log(isPrimitive(new String('hello')))   // false
console.log(isPrimitive(new Number(123)))       // false
console.log(isPrimitive(new Boolean(true)))     // false

// 原始值
console.log(isPrimitive('hello'))               // true
console.log(isPrimitive(123))                   // true
console.log(isPrimitive(true))                  // true

类型守卫使用

typescript
import { isPrimitive } from 'radash'

function processValue(value: unknown) {
  if (isPrimitive(value)) {
    // TypeScript 知道 value 是原始类型
    console.log('Processing primitive:', value)
    return String(value)
  }
  
  console.log('Processing object:', typeof value)
  return JSON.stringify(value)
}

console.log(processValue('hello'))    // Processing primitive: hello hello
console.log(processValue(123))        // Processing primitive: 123 123
console.log(processValue({ a: 1 }))   // Processing object: object {"a":1}

数组过滤

typescript
import { isPrimitive } from 'radash'

const mixedArray = [
  'hello',
  123,
  true,
  null,
  undefined,
  Symbol('test'),
  {},
  [],
  () => {},
  new Date()
]

const primitives = mixedArray.filter(isPrimitive)
console.log(primitives) // ['hello', 123, true, null, undefined, Symbol(test)]

const nonPrimitives = mixedArray.filter(item => !isPrimitive(item))
console.log(nonPrimitives.length) // 4

对象属性检查

typescript
import { isPrimitive } from 'radash'

const data = {
  name: 'Alice',
  age: 25,
  isActive: true,
  email: null,
  settings: { theme: 'dark' },
  hobbies: ['reading', 'coding'],
  greet: () => 'Hello'
}

const primitiveProperties = Object.entries(data)
  .filter(([key, value]) => isPrimitive(value))
  .map(([key, value]) => ({ key, value, type: typeof value }))

console.log(primitiveProperties)
// [
//   { key: 'name', value: 'Alice', type: 'string' },
//   { key: 'age', value: 25, type: 'number' },
//   { key: 'isActive', value: true, type: 'boolean' },
//   { key: 'email', value: null, type: 'object' }
// ]

数据验证

typescript
import { isPrimitive } from 'radash'

interface FormData {
  name: unknown
  age: unknown
  email: unknown
  preferences: unknown
}

function validateFormData(data: FormData) {
  const errors: string[] = []
  
  if (!isPrimitive(data.name) || typeof data.name !== 'string') {
    errors.push('name must be a string')
  }
  
  if (!isPrimitive(data.age) || typeof data.age !== 'number') {
    errors.push('age must be a number')
  }
  
  if (!isPrimitive(data.email) || typeof data.email !== 'string') {
    errors.push('email must be a string')
  }
  
  if (isPrimitive(data.preferences)) {
    errors.push('preferences must be an object')
  }
  
  return errors
}

const validData: FormData = {
  name: 'Alice',
  age: 25,
  email: 'alice@example.com',
  preferences: { theme: 'dark' }
}

const invalidData: FormData = {
  name: { first: 'Alice' },
  age: '25',
  email: null,
  preferences: 'dark'
}

console.log(validateFormData(validData))   // []
console.log(validateFormData(invalidData)) // ['name must be a string', 'age must be a number', 'email must be a string', 'preferences must be an object']

API响应处理

typescript
import { isPrimitive } from 'radash'

interface ApiResponse {
  id: unknown
  name: unknown
  data: unknown
  metadata: unknown
}

function processApiResponse(response: ApiResponse) {
  const processed = {
    id: isPrimitive(response.id) ? response.id : null,
    name: isPrimitive(response.name) ? String(response.name) : '',
    data: isPrimitive(response.data) ? response.data : {},
    metadata: isPrimitive(response.metadata) ? {} : response.metadata
  }
  
  return processed
}

const response1: ApiResponse = {
  id: 1,
  name: 'Alice',
  data: { items: [1, 2, 3] },
  metadata: { created: new Date() }
}

const response2: ApiResponse = {
  id: { id: 1 },
  name: null,
  data: 'not an object',
  metadata: 'not an object'
}

console.log(processApiResponse(response1))
// { id: 1, name: 'Alice', data: {}, metadata: { created: Date } }

console.log(processApiResponse(response2))
// { id: null, name: '', data: 'not an object', metadata: {} }

配置验证

typescript
import { isPrimitive } from 'radash'

interface Config {
  port: unknown
  host: unknown
  timeout: unknown
  options: unknown
}

function validateConfig(config: Config) {
  const errors: string[] = []
  
  if (!isPrimitive(config.port) || typeof config.port !== 'number') {
    errors.push('port must be a number')
  }
  
  if (!isPrimitive(config.host) || typeof config.host !== 'string') {
    errors.push('host must be a string')
  }
  
  if (!isPrimitive(config.timeout) || typeof config.timeout !== 'number') {
    errors.push('timeout must be a number')
  }
  
  if (isPrimitive(config.options)) {
    errors.push('options must be an object')
  }
  
  return errors
}

const validConfig: Config = {
  port: 3000,
  host: 'localhost',
  timeout: 5000,
  options: { debug: true }
}

const invalidConfig: Config = {
  port: '3000',
  host: null,
  timeout: '5s',
  options: 'debug'
}

console.log(validateConfig(validConfig))   // []
console.log(validateConfig(invalidConfig)) // ['port must be a number', 'host must be a string', 'timeout must be a number', 'options must be an object']

数据库记录处理

typescript
import { isPrimitive } from 'radash'

interface DatabaseRecord {
  id: number
  name: unknown
  value: unknown
  metadata: unknown
}

function sanitizeDatabaseRecord(record: DatabaseRecord) {
  return {
    id: record.id,
    name: isPrimitive(record.name) ? String(record.name) : '',
    value: isPrimitive(record.value) ? record.value : null,
    metadata: isPrimitive(record.metadata) ? {} : record.metadata
  }
}

const dbRecord: DatabaseRecord = {
  id: 1,
  name: 'Product A',
  value: 29.99,
  metadata: { category: 'electronics' }
}

console.log(sanitizeDatabaseRecord(dbRecord))
// { id: 1, name: 'Product A', value: 29.99, metadata: { category: 'electronics' } }

事件处理

typescript
import { isPrimitive } from 'radash'

interface EventData {
  type: unknown
  payload: unknown
  timestamp: unknown
}

function processEvent(event: EventData) {
  const processed = {
    type: isPrimitive(event.type) ? String(event.type) : 'unknown',
    payload: isPrimitive(event.payload) ? event.payload : {},
    timestamp: isPrimitive(event.timestamp) ? event.timestamp : Date.now()
  }
  
  return processed
}

const event: EventData = {
  type: 'click',
  payload: { x: 100, y: 200 },
  timestamp: Date.now()
}

console.log(processEvent(event))
// { type: 'click', payload: { x: 100, y: 200 }, timestamp: 1234567890 }

序列化处理

typescript
import { isPrimitive } from 'radash'

function safeSerialize(obj: unknown): string {
  if (isPrimitive(obj)) {
    return JSON.stringify(obj)
  }
  
  if (obj === null) {
    return 'null'
  }
  
  if (typeof obj === 'object') {
    const seen = new WeakSet()
    return JSON.stringify(obj, (key, value) => {
      if (typeof value === 'object' && value !== null) {
        if (seen.has(value)) {
          return '[Circular Reference]'
        }
        seen.add(value)
      }
      return value
    })
  }
  
  return String(obj)
}

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

Object.entries(testData).forEach(([key, value]) => {
  console.log(`${key}: ${safeSerialize(value)}`)
})

类型转换

typescript
import { isPrimitive } from 'radash'

function toPrimitive(value: unknown): string | number | boolean | null | undefined {
  if (isPrimitive(value)) {
    return value
  }
  
  if (value === null) {
    return null
  }
  
  if (typeof value === 'object') {
    return JSON.stringify(value)
  }
  
  return String(value)
}

const testValues = [
  'hello',
  123,
  true,
  null,
  undefined,
  { a: 1, b: 2 },
  [1, 2, 3],
  () => {},
  new Date()
]

testValues.forEach(value => {
  console.log(`${typeof value}: ${toPrimitive(value)}`)
})

深度检查

typescript
import { isPrimitive } from 'radash'

function hasOnlyPrimitives(obj: unknown): boolean {
  if (isPrimitive(obj)) {
    return true
  }
  
  if (obj === null || typeof obj !== 'object') {
    return false
  }
  
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (!hasOnlyPrimitives(obj[key])) {
        return false
      }
    }
  }
  
  return true
}

const obj1 = {
  name: 'Alice',
  age: 25,
  settings: {
    theme: 'dark',
    notifications: true
  }
}

const obj2 = {
  name: 'Bob',
  data: { items: [1, 2, 3] },
  func: () => {}
}

console.log(hasOnlyPrimitives(obj1)) // true
console.log(hasOnlyPrimitives(obj2)) // false

性能测试

typescript
import { isPrimitive } from 'radash'

function benchmarkIsPrimitive() {
  const testValues = [
    'hello', 123, true, null, undefined, Symbol('test'),
    {}, [], () => {}, new Date(), new RegExp('')
  ]
  
  const iterations = 1000000
  const start = performance.now()
  
  for (let i = 0; i < iterations; i++) {
    testValues.forEach(value => {
      isPrimitive(value)
    })
  }
  
  const end = performance.now()
  console.log(`Benchmark completed in ${end - start}ms`)
}

// benchmarkIsPrimitive() // 运行性能测试

边界值测试

typescript
import { isPrimitive } from 'radash'

// 测试边界值
const boundaryTests = [
  // 字符串边界
  '',
  ' ',
  '0',
  'false',
  'null',
  'undefined',
  
  // 数字边界
  0,
  -0,
  1,
  -1,
  Number.MAX_VALUE,
  Number.MIN_VALUE,
  Number.MAX_SAFE_INTEGER,
  Number.MIN_SAFE_INTEGER,
  Infinity,
  -Infinity,
  NaN,
  
  // 布尔值
  true,
  false,
  
  // null 和 undefined
  null,
  undefined,
  
  // Symbol
  Symbol(),
  Symbol('test'),
  Symbol.iterator,
  
  // 包装对象
  new String('hello'),
  new Number(123),
  new Boolean(true),
  
  // 其他对象
  {},
  [],
  () => {},
  new Date(),
  new RegExp(''),
  new Map(),
  new Set()
]

boundaryTests.forEach(value => {
  console.log(`${typeof value} ${JSON.stringify(value)}: ${isPrimitive(value)}`)
})

注意事项

  1. 原始类型定义: 包括string、number、boolean、null、undefined、symbol
  2. 包装对象: 包装对象(如new String())不被认为是原始类型
  3. 类型守卫: 作为TypeScript类型守卫使用
  4. 性能: 检查速度很快,适合高频使用
  5. 边界值: 正确处理所有边界情况

与其他方法的区别

  • isPrimitive(): 检查是否为原始类型
  • typeof value !== 'object': 简单但不够准确
  • value !== null && typeof value !== 'object': 排除null的对象检查
  • typeof value === 'string' || typeof value === 'number' || ...: 逐个类型检查

实际应用场景

  1. 数据验证: 验证API响应中的原始类型字段
  2. 类型转换: 确保值可以安全转换为原始类型
  3. 序列化: 处理需要序列化的数据
  4. 表单处理: 验证表单输入类型
  5. 配置验证: 验证配置中的原始类型值
  6. 数据库操作: 验证数据库字段类型

Released under the MIT License.