-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathhas.ts
81 lines (65 loc) · 2.13 KB
/
has.ts
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
import {Many, PropertyPath} from './internal/types'
import isArray from './isArray'
const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/
const reIsPlainProp = /^\w*$/
function isKey(value: PropertyPath, object: unknown): boolean {
if (Array.isArray(value)) {
return false
}
if (typeof value !== 'string') {
return false
}
return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || (object != null && value in Object(object))
}
function castPath(value: Many<string | number | symbol>): string[] {
if (Array.isArray(value)) {
return value.map(String)
}
if (typeof value === 'string') {
return value.split('.')
}
return [String(value)]
}
function hasPath(object: unknown, path: PropertyPath): boolean {
if (object == null) {
return false
}
const pathArray = isKey(path, object) ? [path as string] : castPath(path)
let currentObject: unknown = object
for (let i = 0; i < pathArray.length; i++) {
const key = pathArray[i]
if (
currentObject == null ||
typeof currentObject !== 'object' ||
typeof key !== 'string' ||
!Object.prototype.hasOwnProperty.call(currentObject, key)
) {
return false
}
currentObject = (currentObject as Record<string, unknown>)[key]
if (i === pathArray.length - 1) {
return true
}
}
return true
}
/**
* @description https://unpkg.com/browse/lodash.has@4.5.2/index.js
*/
export function has(object: unknown, path: PropertyPath): boolean {
if (path == null || (Array.isArray(path) && !path.length)) {
return false
}
if (typeof path === 'string') {
if (!path || path === '.' || path === '..') {
return false
}
if (!path.includes('.')) {
return object != null && typeof object === 'object' && Object.prototype.hasOwnProperty.call(object, path)
}
} else if (isArray(path) && !path.every((segment) => typeof segment === 'string')) {
return false
}
return hasPath(object, path)
}
export default has