Skip to content

Commit 9bec8ac

Browse files
committed
feat(utils): isObjectLike
Signed-off-by: Lexus Drumgold <unicornware@flexdevelopment.llc>
1 parent 10fa0a9 commit 9bec8ac

File tree

8 files changed

+121
-29
lines changed

8 files changed

+121
-29
lines changed

src/utils/__tests__/is-object-curly.spec.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,41 @@
33
* @module tutils/utils/tests/unit/isObjectCurly
44
*/
55

6+
import INTEGER from '#fixtures/integer'
7+
import TODAY from '#fixtures/today'
8+
import VEHICLE from '#fixtures/vehicle'
69
import testSubject from '../is-object-curly'
710

811
describe('unit:utils/isObjectCurly', () => {
9-
it('should return false if value is not curly-braced object', () => {
12+
it('should return false if value is array', () => {
13+
expect(testSubject([])).to.be.false
14+
})
15+
16+
it('should return false if value is function', () => {
17+
expect(testSubject(vi.fn())).to.be.false
18+
})
19+
20+
it('should return false if value is a primitive', () => {
1021
// Arrange
1122
const cases: Parameters<typeof testSubject>[] = [
12-
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]],
23+
[INTEGER],
24+
[VEHICLE.vin],
25+
[faker.datatype.boolean()],
26+
[faker.number.bigInt()],
1327
[faker.string.hexadecimal({ length: 24 })],
14-
[vi.fn()]
28+
[null],
29+
[undefined]
1530
]
1631

1732
// Act + Expect
1833
cases.forEach(([value]) => expect(testSubject(value)).to.be.false)
1934
})
2035

21-
it('should return true if value is curly-braced object', () => {
22-
// Arrange
23-
const cases: Parameters<typeof testSubject>[] = [
24-
[faker.date.anytime()],
25-
[{ email: faker.internet.email() }]
26-
]
36+
it('should return true if value is instance object', () => {
37+
expect(testSubject(TODAY)).to.be.true
38+
})
2739

28-
// Act + Expect
29-
cases.forEach(([value]) => expect(testSubject(value)).to.be.true)
40+
it('should return true if value is plain object', () => {
41+
expect(testSubject(VEHICLE)).to.be.true
3042
})
3143
})
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* @file Type Tests - isObjectLike
3+
* @module tutils/utils/tests/unit-d/isObjectLike
4+
*/
5+
6+
import type { ObjectCurly } from '#src/types'
7+
import type testSubject from '../is-object-like'
8+
9+
describe('unit-d:utils/isObjectLike', () => {
10+
it('should guard ObjectCurly | unknown[]', () => {
11+
// Arrange
12+
type Expect = ObjectCurly | unknown[]
13+
14+
// Expect
15+
expectTypeOf<typeof testSubject>().guards.toEqualTypeOf<Expect>()
16+
})
17+
})
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* @file Unit Tests - isObjectLike
3+
* @module tutils/utils/tests/unit/isObjectLike
4+
*/
5+
6+
import INTEGER from '#fixtures/integer'
7+
import TODAY from '#fixtures/today'
8+
import VEHICLE from '#fixtures/vehicle'
9+
import testSubject from '../is-object-like'
10+
11+
describe('unit:utils/isObjectLike', () => {
12+
it('should return false if value is function', () => {
13+
expect(testSubject(vi.fn())).to.be.false
14+
})
15+
16+
it('should return false if value is a primitive', () => {
17+
// Arrange
18+
const cases: Parameters<typeof testSubject>[] = [
19+
[INTEGER],
20+
[VEHICLE.vin],
21+
[faker.datatype.boolean()],
22+
[faker.number.bigInt()],
23+
[faker.string.sample()],
24+
[null],
25+
[undefined]
26+
]
27+
28+
// Act + Expect
29+
cases.forEach(([value]) => expect(testSubject(value)).to.be.false)
30+
})
31+
32+
it('should return true if value is array', () => {
33+
expect(testSubject([])).to.be.true
34+
})
35+
36+
it('should return true if value is instance object', () => {
37+
expect(testSubject(TODAY)).to.be.true
38+
})
39+
40+
it('should return true if value is plain object', () => {
41+
expect(testSubject(VEHICLE)).to.be.true
42+
})
43+
})

src/utils/__tests__/is-object.spec.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,15 @@
44
*/
55

66
import INTEGER from '#fixtures/integer'
7-
import VEHICLE, { VEHICLE_TAG } from '#fixtures/vehicle'
8-
import type { tag as opaque } from '#src/types/opaque'
9-
import cast from '../cast'
7+
import TODAY from '#fixtures/today'
8+
import VEHICLE from '#fixtures/vehicle'
109
import testSubject from '../is-object'
1110

1211
describe('unit:utils/isObject', () => {
1312
it('should return false if value is a primitive', () => {
1413
// Arrange
1514
const cases: Parameters<typeof testSubject>[] = [
1615
[INTEGER],
17-
[VEHICLE[cast<typeof opaque>(VEHICLE_TAG)]],
1816
[VEHICLE.vin],
1917
[faker.datatype.boolean()],
2018
[faker.number.bigInt()],
@@ -36,10 +34,10 @@ describe('unit:utils/isObject', () => {
3634
})
3735

3836
it('should return true if value is instance object', () => {
39-
expect(testSubject(faker.date.anytime())).to.be.true
37+
expect(testSubject(TODAY)).to.be.true
4038
})
4139

4240
it('should return true if value is plain object', () => {
43-
expect(testSubject({ job_title: faker.person.jobTitle() })).to.be.true
41+
expect(testSubject(VEHICLE)).to.be.true
4442
})
4543
})

src/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export { default as isNumber } from './is-number'
7575
export { default as isNumeric } from './is-numeric'
7676
export { default as isObject } from './is-object'
7777
export { default as isObjectCurly } from './is-object-curly'
78+
export { default as isObjectLike } from './is-object-like'
7879
export { default as isObjectPlain } from './is-object-plain'
7980
export { default as isPrimitive } from './is-primitive'
8081
export { default as isPromise } from './is-promise'

src/utils/is-object-curly.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,23 @@
55

66
import type { ObjectCurly } from '#src/types'
77
import isArray from './is-array'
8-
import isFunction from './is-function'
9-
import isObject from './is-object'
10-
import isObjectPlain from './is-object-plain'
8+
import isObjectLike from './is-object-like'
119

1210
/**
1311
* Checks if `value` is a curly-braced object.
1412
*
15-
* A curly-braced object is an object that is not an array or function (e.g.
16-
* instance objects, pojos).
13+
* A curly-braced object is an object-like value that is not an array.
1714
*
1815
* @see {@linkcode ObjectCurly}
16+
* @see {@linkcode isObjectLike}
1917
*
2018
* @todo examples
2119
*
2220
* @param {unknown} value - Value to check
2321
* @return {value is ObjectCurly} `true` if `value` is curly-braced object
2422
*/
2523
const isObjectCurly = (value: unknown): value is ObjectCurly => {
26-
return (
27-
isObjectPlain(value) ||
28-
(!isArray(value) && !isFunction(value) && isObject(value))
29-
)
24+
return !isArray(value) && isObjectLike(value)
3025
}
3126

3227
export default isObjectCurly

src/utils/is-object-like.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @file Utilities - isObjectLike
3+
* @module tutils/utils/isObjectLike
4+
*/
5+
6+
import type { ObjectCurly } from '#src/types'
7+
import isNull from './is-null'
8+
9+
/**
10+
* Checks if `value` is object-like.
11+
*
12+
* A value is object-like if it has a `typeof` result of `'object'` and is not
13+
* `null`.
14+
*
15+
* @todo examples
16+
*
17+
* @param {unknown} value - Value to check
18+
* @return {value is ObjectCurly | unknown[]} `true` if `value` is object-like
19+
*/
20+
const isObjectLike = (value: unknown): value is ObjectCurly | unknown[] => {
21+
return !isNull(value) && typeof value === 'object'
22+
}
23+
24+
export default isObjectLike

src/utils/is-object.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55

66
import type { Objectify } from '#src/types'
77
import isFunction from './is-function'
8-
import isNull from './is-null'
8+
import isObjectLike from './is-object-like'
99

1010
/**
11-
* Checks if `value` is an object.
11+
* Checks if `value` is a [language type][1] `Object`.
1212
*
1313
* Object types include:
1414
*
@@ -17,13 +17,15 @@ import isNull from './is-null'
1717
* - instance objects
1818
* - plain objects (pojos)
1919
*
20+
* [1]: http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types
21+
*
2022
* @todo examples
2123
*
2224
* @param {unknown} value - Value to check
2325
* @return {value is Objectify<any>} `true` if `value` is an object
2426
*/
2527
const isObject = (value: unknown): value is Objectify<any> => {
26-
return isFunction(value) || (typeof value === 'object' && !isNull(value))
28+
return isFunction(value) || isObjectLike(value)
2729
}
2830

2931
export default isObject

0 commit comments

Comments
 (0)