-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpredicates.ts
More file actions
133 lines (127 loc) · 3.92 KB
/
predicates.ts
File metadata and controls
133 lines (127 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* @fileoverview Object type guards: `hasKeys`, `hasOwn`, `isObject`,
* `isPlainObject`. All four narrow `unknown` to a typed shape and
* tolerate `null` / `undefined` without throwing.
*/
import { isArray } from '../arrays/predicates'
import {
ObjectGetPrototypeOf,
ObjectHasOwn,
ObjectPrototype,
} from '../primordials/object'
import type { PropertyBag } from './types'
/**
* Check if an object has any enumerable own properties.
*
* Returns `true` if the object has at least one enumerable own property,
* `false` otherwise. Also returns `false` for null/undefined.
*
* @param obj - The value to check
* @returns `true` if obj has enumerable own properties, `false` otherwise
*
* @example
* ```ts
* hasKeys({ a: 1 }) // true
* hasKeys({}) // false
* hasKeys([]) // false
* hasKeys([1, 2]) // true
* hasKeys(null) // false
* hasKeys(undefined) // false
* hasKeys(Object.create({ inherited: true })) // false
* ```
*/
/*@__NO_SIDE_EFFECTS__*/
export function hasKeys(obj: unknown): obj is PropertyBag {
if (obj === null || obj === undefined) {
return false
}
for (const key in obj as object) {
if (ObjectHasOwn(obj as object, key)) {
return true
}
}
return false
}
/**
* Check if an object has an own property.
*
* Type-safe wrapper around `Object.hasOwn()` that returns `false` for
* null/undefined instead of throwing. Only checks own properties, not
* inherited ones from the prototype chain.
*
* @param obj - The value to check
* @param propKey - The property key to look for
* @returns `true` if obj has the property as an own property, `false` otherwise
*
* @example
* ```ts
* const obj = { name: 'Alice' }
* hasOwn(obj, 'name') // true
* hasOwn(obj, 'age') // false
* hasOwn(obj, 'toString') // false (inherited)
* hasOwn(null, 'name') // false
* ```
*/
/*@__NO_SIDE_EFFECTS__*/
export function hasOwn(
obj: unknown,
propKey: PropertyKey,
): obj is object & PropertyBag {
if (obj === null || obj === undefined) {
return false
}
return ObjectHasOwn(obj as object, propKey)
}
/**
* Check if a value is an object (including arrays).
*
* Returns `true` for any object type including arrays, dates, etc.
* Returns `false` for primitives and `null`. Functions are not
* considered objects here (typeof functions === 'function').
*
* @param value - The value to check
* @returns `true` if value is an object (including arrays), `false` otherwise
*
* @example
* ```ts
* isObject({}) // true
* isObject([]) // true
* isObject(new Date()) // true
* isObject(() => {}) // false
* isObject(null) // false
* ```
*/
/*@__NO_SIDE_EFFECTS__*/
export function isObject(
value: unknown,
): value is { [key: PropertyKey]: unknown } {
return value !== null && typeof value === 'object'
}
/**
* Check if a value is a plain object (not an array, not a built-in).
*
* Returns `true` only for plain objects created with `{}` or `Object.create(null)`.
* Returns `false` for arrays, built-in objects (Date, RegExp, etc.), and primitives.
*
* @param value - The value to check
* @returns `true` if value is a plain object, `false` otherwise
*
* @example
* ```ts
* isPlainObject({}) // true
* isPlainObject({ a: 1 }) // true
* isPlainObject(Object.create(null)) // true
* isPlainObject([]) // false
* isPlainObject(new Date()) // false
* ```
*/
/*@__NO_SIDE_EFFECTS__*/
export function isPlainObject(
value: unknown,
): value is { [key: PropertyKey]: unknown } {
if (value === null || typeof value !== 'object' || isArray(value)) {
return false
}
const proto: object | null = ObjectGetPrototypeOf(value)
return proto === null || proto === ObjectPrototype
}