Skip to content

Commit ab8b322

Browse files
committed
feat: new isPrimitive and objectId function
1 parent 3855330 commit ab8b322

File tree

5 files changed

+64
-3
lines changed

5 files changed

+64
-3
lines changed

src/is.test.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { expect, it } from 'vitest'
2+
import { isPrimitive } from './is'
3+
4+
it('isPrimitive', () => {
5+
expect(isPrimitive(null)).toBe(true)
6+
expect(isPrimitive(undefined)).toBe(true)
7+
expect(isPrimitive(0)).toBe(true)
8+
expect(isPrimitive('')).toBe(true)
9+
expect(isPrimitive(Symbol('foo'))).toBe(true)
10+
expect(isPrimitive(1n)).toBe(true)
11+
12+
expect(isPrimitive([])).toBe(false)
13+
expect(isPrimitive({})).toBe(false)
14+
15+
class Foo {}
16+
expect(isPrimitive(new Foo())).toBe(false)
17+
expect(isPrimitive(new Map())).toBe(false)
18+
})

src/is.ts

+7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ export const isNull = (val: any): val is null => toString(val) === '[object Null
1212
export const isRegExp = (val: any): val is RegExp => toString(val) === '[object RegExp]'
1313
export const isDate = (val: any): val is Date => toString(val) === '[object Date]'
1414

15+
/**
16+
* Check if a value is primitive
17+
*/
18+
export function isPrimitive(val: any): val is string | number | boolean | symbol | bigint | null | undefined {
19+
return !val || Object(val) !== val
20+
}
21+
1522
// @ts-expect-error
1623
export const isWindow = (val: any): boolean => typeof window !== 'undefined' && toString(val) === '[object Window]'
1724
// @ts-expect-error

src/object.test.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from 'vitest'
2-
import { deepMerge, deepMergeWithArray, objectMap } from './object'
2+
import { deepMerge, deepMergeWithArray, objectId, objectMap } from './object'
33

44
it('objectMap', () => {
55
expect(objectMap({}, (...args) => args)).toEqual({})
@@ -77,3 +77,19 @@ describe('deepMergeWithArray', () => {
7777
expect(deepMergeWithArray({}, obj1, obj2)).toEqual({ a: ['A', 'B', 'C'], b: ['D'] })
7878
})
7979
})
80+
81+
it('objectId', () => {
82+
const foo = { a: 1, b: 2 }
83+
const bar = new Map()
84+
// eslint-disable-next-line prefer-regex-literals
85+
const baz = new RegExp('foo', 'g')
86+
87+
expect(objectId(foo)).toBe(objectId(foo))
88+
expect(objectId(bar)).toBe(objectId(bar))
89+
expect(objectId(baz)).toBe(objectId(baz))
90+
91+
expect(objectId(foo)).not.toBe(objectId(bar))
92+
expect(objectId({})).not.toBe(objectId({}))
93+
expect(objectId([])).not.toBe(objectId([]))
94+
expect(objectId(/a/)).not.toBe(objectId(/a/))
95+
})

src/object.ts

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { DeepMerge } from './types'
22
import { notNullish } from './guards'
3-
import { isObject } from './is'
3+
import { isObject, isPrimitive } from './is'
4+
import { randomStr } from './string'
45

56
/**
67
* Map key/value pairs for an object, and construct a new one
@@ -211,3 +212,22 @@ export function hasOwnProperty<T>(obj: T, v: PropertyKey) {
211212
return false
212213
return Object.prototype.hasOwnProperty.call(obj, v)
213214
}
215+
216+
const _objectIdMap = /* @__PURE__ */ new WeakMap<WeakKey, string>()
217+
/**
218+
* Get an object's unique identifier
219+
*
220+
* Same object will always return the same id
221+
*
222+
* Expect argument to be a non-primitive object/array. Primitive values will be returned as is.
223+
*
224+
* @category Object
225+
*/
226+
export function objectId(obj: WeakKey): string {
227+
if (isPrimitive(obj))
228+
return obj as unknown as string
229+
if (!_objectIdMap.has(obj)) {
230+
_objectIdMap.set(obj, randomStr())
231+
}
232+
return _objectIdMap.get(obj)!
233+
}

tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"compilerOptions": {
3-
"target": "es2018",
3+
"target": "es2020",
44
"lib": ["esnext"],
55
"module": "esnext",
66
"moduleResolution": "node",

0 commit comments

Comments
 (0)