@cloudcome/utils-core 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/LICENSE +21 -0
- package/package.json +279 -1
- package/src/array.ts +312 -0
- package/src/async.ts +379 -0
- package/src/base64.ts +20 -0
- package/src/cache.ts +146 -0
- package/{dist/color/contrast.d.ts → src/color/contrast.ts} +12 -2
- package/src/color/distance.ts +28 -0
- package/src/color/helpers.ts +23 -0
- package/src/color/hex-hsl.ts +11 -0
- package/{dist/color/hex-hsv.d.ts → src/color/hex-hsv.ts} +11 -3
- package/{dist/color/hex-hwb.d.ts → src/color/hex-hwb.ts} +11 -3
- package/src/color/hex-rgb.ts +39 -0
- package/{dist/color/hsl-lighten.d.ts → src/color/hsl-lighten.ts} +7 -2
- package/{dist/color/hsv-brighten.d.ts → src/color/hsv-brighten.ts} +7 -2
- package/{dist/color/luminance.d.ts → src/color/luminance.ts} +9 -2
- package/{dist/color/mix.d.ts → src/color/mix.ts} +10 -2
- package/src/color/rgb-hsl.ts +53 -0
- package/{dist/color/rgb-hsv.d.ts → src/color/rgb-hsv.ts} +30 -3
- package/src/color/rgb-hwb.ts +56 -0
- package/{dist/color/rgb-lab.d.ts → src/color/rgb-lab.ts} +11 -3
- package/src/color/rgb-whiter.ts +22 -0
- package/src/color/rgb-xyz.ts +62 -0
- package/{dist/color/types.d.ts → src/color/types.ts} +12 -30
- package/{dist/color/xyz-lab.d.ts → src/color/xyz-lab.ts} +32 -3
- package/src/crypto/md5.mjs +357 -0
- package/src/crypto/sha1.mjs +300 -0
- package/src/crypto/sha256.mjs +310 -0
- package/src/crypto/sha512.mjs +459 -0
- package/{dist/crypto.d.ts → src/crypto.ts} +20 -4
- package/src/date/const.ts +6 -0
- package/src/date/core.ts +162 -0
- package/src/date/days.ts +51 -0
- package/{dist/date/is.d.ts → src/date/is.ts} +102 -8
- package/src/date/relative.ts +92 -0
- package/src/date/start-end.ts +246 -0
- package/src/date/timezone.ts +220 -0
- package/src/date/weeks.ts +100 -0
- package/src/dts/global.d.ts +27 -0
- package/src/easing.ts +166 -0
- package/src/emitter.ts +117 -0
- package/src/enum.ts +171 -0
- package/{dist/env.d.ts → src/env.ts} +30 -6
- package/{dist/error.d.ts → src/error.ts} +12 -3
- package/src/exception.ts +68 -0
- package/src/fn.ts +197 -0
- package/src/index.ts +1 -0
- package/src/number.ts +236 -0
- package/{dist/object/each.d.ts → src/object/each.ts} +23 -3
- package/src/object/get-set.ts +273 -0
- package/src/object/is.ts +128 -0
- package/src/object/merge.ts +180 -0
- package/{dist/object/process.d.ts → src/object/process.ts} +38 -4
- package/src/path.ts +188 -0
- package/{dist/promise.d.ts → src/promise.ts} +67 -6
- package/{dist/qs.d.ts → src/qs.ts} +60 -3
- package/src/regexp.ts +156 -0
- package/src/string.ts +146 -0
- package/src/time/from.ts +57 -0
- package/src/time/to.ts +106 -0
- package/{dist/timer.mjs → src/timer.ts} +124 -17
- package/{dist/tree.d.ts → src/tree.ts} +225 -41
- package/{dist/type.d.ts → src/type.ts} +96 -20
- package/{dist/types.d.ts → src/types.ts} +33 -12
- package/src/unique.ts +77 -0
- package/src/url.ts +93 -0
- package/src/version.ts +71 -0
- package/test/array.test.ts +332 -0
- package/test/async-real.test.ts +39 -0
- package/test/async.test.ts +375 -0
- package/test/base64.test.ts +32 -0
- package/test/cache.test.ts +83 -0
- package/test/color.test.ts +163 -0
- package/test/crypto.test.ts +34 -0
- package/test/date-tz.test.ts +206 -0
- package/test/date.test.ts +353 -0
- package/test/easing.test.ts +33 -0
- package/test/emitter.test.ts +71 -0
- package/test/enum.test.ts +113 -0
- package/test/env.test.ts +69 -0
- package/test/error.test.ts +58 -0
- package/test/exception.test.ts +43 -0
- package/test/fn.test.ts +263 -0
- package/test/helpers.ts +23 -0
- package/test/index.test.ts +6 -0
- package/test/number.test.ts +213 -0
- package/test/object.test.ts +309 -0
- package/test/path.test.ts +156 -0
- package/test/promise.test.ts +199 -0
- package/test/qs.test.ts +79 -0
- package/test/regexp.test.ts +97 -0
- package/test/string.test.ts +150 -0
- package/test/time.test.ts +214 -0
- package/test/timer.test.ts +114 -0
- package/test/tree.test.ts +348 -0
- package/test/type.test.ts +226 -0
- package/test/unique.test.ts +71 -0
- package/test/url.test.ts +136 -0
- package/test/version.test.ts +52 -0
- package/tsconfig.json +31 -0
- package/vite.config.mts +114 -0
- package/dist/array.cjs +0 -129
- package/dist/array.cjs.map +0 -1
- package/dist/array.d.ts +0 -171
- package/dist/array.mjs +0 -129
- package/dist/array.mjs.map +0 -1
- package/dist/async.cjs +0 -219
- package/dist/async.cjs.map +0 -1
- package/dist/async.d.ts +0 -137
- package/dist/async.mjs +0 -219
- package/dist/async.mjs.map +0 -1
- package/dist/base64.cjs +0 -16
- package/dist/base64.cjs.map +0 -1
- package/dist/base64.d.ts +0 -7
- package/dist/base64.mjs +0 -16
- package/dist/base64.mjs.map +0 -1
- package/dist/cache.cjs +0 -79
- package/dist/cache.cjs.map +0 -1
- package/dist/cache.d.ts +0 -90
- package/dist/cache.mjs +0 -79
- package/dist/cache.mjs.map +0 -1
- package/dist/color/distance.d.ts +0 -8
- package/dist/color/helpers.d.ts +0 -2
- package/dist/color/hex-hsl.d.ts +0 -3
- package/dist/color/hex-rgb.d.ts +0 -18
- package/dist/color/rgb-hsl.d.ts +0 -23
- package/dist/color/rgb-hwb.d.ts +0 -29
- package/dist/color/rgb-whiter.d.ts +0 -12
- package/dist/color/rgb-xyz.d.ts +0 -22
- package/dist/color.cjs +0 -250
- package/dist/color.cjs.map +0 -1
- package/dist/color.mjs +0 -250
- package/dist/color.mjs.map +0 -1
- package/dist/const.cjs +0 -14
- package/dist/const.cjs.map +0 -1
- package/dist/const.mjs +0 -15
- package/dist/const.mjs.map +0 -1
- package/dist/core.cjs +0 -250
- package/dist/core.cjs.map +0 -1
- package/dist/core.mjs +0 -251
- package/dist/core.mjs.map +0 -1
- package/dist/crypto/md5.d.mts +0 -1
- package/dist/crypto/sha1.d.mts +0 -1
- package/dist/crypto/sha256.d.mts +0 -1
- package/dist/crypto/sha512.d.mts +0 -1
- package/dist/crypto.cjs +0 -812
- package/dist/crypto.cjs.map +0 -1
- package/dist/crypto.mjs +0 -812
- package/dist/crypto.mjs.map +0 -1
- package/dist/date/const.d.ts +0 -6
- package/dist/date/core.d.ts +0 -52
- package/dist/date/days.d.ts +0 -23
- package/dist/date/relative.d.ts +0 -44
- package/dist/date/start-end.d.ts +0 -73
- package/dist/date/timezone.d.ts +0 -67
- package/dist/date/weeks.d.ts +0 -72
- package/dist/date.cjs +0 -239
- package/dist/date.cjs.map +0 -1
- package/dist/date.mjs +0 -241
- package/dist/date.mjs.map +0 -1
- package/dist/dict.cjs +0 -2
- package/dist/dict.cjs.map +0 -1
- package/dist/dict.mjs +0 -2
- package/dist/dict.mjs.map +0 -1
- package/dist/each.cjs +0 -18
- package/dist/each.cjs.map +0 -1
- package/dist/each.mjs +0 -19
- package/dist/each.mjs.map +0 -1
- package/dist/easing.cjs +0 -151
- package/dist/easing.cjs.map +0 -1
- package/dist/easing.d.ts +0 -46
- package/dist/easing.mjs +0 -151
- package/dist/easing.mjs.map +0 -1
- package/dist/emitter.cjs +0 -94
- package/dist/emitter.cjs.map +0 -1
- package/dist/emitter.d.ts +0 -68
- package/dist/emitter.mjs +0 -94
- package/dist/emitter.mjs.map +0 -1
- package/dist/enum.cjs +0 -58
- package/dist/enum.cjs.map +0 -1
- package/dist/enum.d.ts +0 -68
- package/dist/enum.mjs +0 -58
- package/dist/enum.mjs.map +0 -1
- package/dist/env.cjs +0 -28
- package/dist/env.cjs.map +0 -1
- package/dist/env.mjs +0 -28
- package/dist/env.mjs.map +0 -1
- package/dist/error.cjs +0 -12
- package/dist/error.cjs.map +0 -1
- package/dist/error.mjs +0 -12
- package/dist/error.mjs.map +0 -1
- package/dist/exception.cjs +0 -22
- package/dist/exception.cjs.map +0 -1
- package/dist/exception.d.ts +0 -31
- package/dist/exception.mjs +0 -22
- package/dist/exception.mjs.map +0 -1
- package/dist/fn.cjs +0 -76
- package/dist/fn.cjs.map +0 -1
- package/dist/fn.d.ts +0 -102
- package/dist/fn.mjs +0 -76
- package/dist/fn.mjs.map +0 -1
- package/dist/index.cjs +0 -5
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +0 -5
- package/dist/index.mjs.map +0 -1
- package/dist/merge.cjs +0 -87
- package/dist/merge.cjs.map +0 -1
- package/dist/merge.mjs +0 -88
- package/dist/merge.mjs.map +0 -1
- package/dist/number.cjs +0 -11
- package/dist/number.cjs.map +0 -1
- package/dist/number.d.ts +0 -137
- package/dist/number.mjs +0 -11
- package/dist/number.mjs.map +0 -1
- package/dist/object/get-set.d.ts +0 -111
- package/dist/object/is.d.ts +0 -32
- package/dist/object/merge.d.ts +0 -72
- package/dist/object.cjs +0 -130
- package/dist/object.cjs.map +0 -1
- package/dist/object.mjs +0 -130
- package/dist/object.mjs.map +0 -1
- package/dist/path.cjs +0 -77
- package/dist/path.cjs.map +0 -1
- package/dist/path.d.ts +0 -82
- package/dist/path.mjs +0 -77
- package/dist/path.mjs.map +0 -1
- package/dist/promise.cjs +0 -62
- package/dist/promise.cjs.map +0 -1
- package/dist/promise.mjs +0 -62
- package/dist/promise.mjs.map +0 -1
- package/dist/qs.cjs +0 -47
- package/dist/qs.cjs.map +0 -1
- package/dist/qs.mjs +0 -47
- package/dist/qs.mjs.map +0 -1
- package/dist/regexp.cjs +0 -66
- package/dist/regexp.cjs.map +0 -1
- package/dist/regexp.d.ts +0 -65
- package/dist/regexp.mjs +0 -66
- package/dist/regexp.mjs.map +0 -1
- package/dist/string.cjs +0 -16
- package/dist/string.cjs.map +0 -1
- package/dist/string.d.ts +0 -80
- package/dist/string.mjs +0 -16
- package/dist/string.mjs.map +0 -1
- package/dist/string2.cjs +0 -147
- package/dist/string2.cjs.map +0 -1
- package/dist/string2.mjs +0 -148
- package/dist/string2.mjs.map +0 -1
- package/dist/time/from.d.ts +0 -14
- package/dist/time/to.d.ts +0 -38
- package/dist/time.cjs +0 -82
- package/dist/time.cjs.map +0 -1
- package/dist/time.mjs +0 -82
- package/dist/time.mjs.map +0 -1
- package/dist/timer.cjs +0 -119
- package/dist/timer.cjs.map +0 -1
- package/dist/timer.d.ts +0 -96
- package/dist/timer.mjs.map +0 -1
- package/dist/tree.cjs +0 -125
- package/dist/tree.cjs.map +0 -1
- package/dist/tree.mjs +0 -125
- package/dist/tree.mjs.map +0 -1
- package/dist/type.cjs +0 -78
- package/dist/type.cjs.map +0 -1
- package/dist/type.mjs +0 -78
- package/dist/type.mjs.map +0 -1
- package/dist/types.cjs +0 -2
- package/dist/types.cjs.map +0 -1
- package/dist/types.mjs +0 -2
- package/dist/types.mjs.map +0 -1
- package/dist/unique.cjs +0 -46
- package/dist/unique.cjs.map +0 -1
- package/dist/unique.d.ts +0 -22
- package/dist/unique.mjs +0 -46
- package/dist/unique.mjs.map +0 -1
- package/dist/url.cjs +0 -37
- package/dist/url.cjs.map +0 -1
- package/dist/url.d.ts +0 -53
- package/dist/url.mjs +0 -37
- package/dist/url.mjs.map +0 -1
- package/dist/version.cjs +0 -33
- package/dist/version.cjs.map +0 -1
- package/dist/version.d.ts +0 -32
- package/dist/version.mjs +0 -33
- package/dist/version.mjs.map +0 -1
- /package/{dist/color.d.ts → src/color.ts} +0 -0
- /package/{dist/date.d.ts → src/date.ts} +0 -0
- /package/{dist/dict.d.ts → src/dict.ts} +0 -0
- /package/{dist/object.d.ts → src/object.ts} +0 -0
- /package/{dist/time.d.ts → src/time.ts} +0 -0
|
@@ -1,57 +1,68 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { arrayEach } from './array';
|
|
2
|
+
import { isArray, isNullish, isUndefined } from './type';
|
|
3
|
+
import type { AnyObject } from './types';
|
|
4
|
+
|
|
2
5
|
/**
|
|
3
6
|
* 表示深度遍历中的节点对象,包含子节点列表。
|
|
4
7
|
*/
|
|
5
8
|
export type TTreeItem = AnyObject & {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* 子节点列表。
|
|
11
|
+
*/
|
|
12
|
+
children?: TTreeItem[];
|
|
10
13
|
};
|
|
14
|
+
|
|
11
15
|
/**
|
|
12
16
|
* 表示深度遍历中的节点列表。
|
|
13
17
|
*
|
|
14
18
|
* @template I - 节点对象的类型,必须继承自 `TreeItem`。
|
|
15
19
|
*/
|
|
16
20
|
export type TTreeList<I extends TTreeItem> = I[];
|
|
21
|
+
|
|
17
22
|
/**
|
|
18
23
|
* 表示深度遍历中的遍历器状态。
|
|
19
24
|
*
|
|
20
25
|
* @template I - 节点对象的类型,必须继承自 `TreeItem`。
|
|
21
26
|
*/
|
|
22
27
|
export type TTreeWalker<I extends TTreeItem> = {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
/**
|
|
29
|
+
* 当前层级的节点列表。
|
|
30
|
+
*/
|
|
31
|
+
list: TTreeList<I>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 当前节点的父节点,如果为根节点则为 `null`。
|
|
35
|
+
*/
|
|
36
|
+
parent: I | null;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 当前节点的层级,从 1 开始计数。
|
|
40
|
+
*/
|
|
41
|
+
level: number;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 从根节点到当前节点的路径。
|
|
45
|
+
*/
|
|
46
|
+
path: TTreeList<I>;
|
|
39
47
|
};
|
|
48
|
+
|
|
40
49
|
/**
|
|
41
50
|
* 表示深度遍历中的节点信息。
|
|
42
51
|
*
|
|
43
52
|
* @template I - 节点对象的类型,必须继承自 `TreeItem`。
|
|
44
53
|
*/
|
|
45
54
|
export type TTreeInfo<I extends TTreeItem> = TTreeWalker<I> & {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
/**
|
|
56
|
+
* 当前节点。
|
|
57
|
+
*/
|
|
58
|
+
item: I;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 当前节点在 `list` 中的索引。
|
|
62
|
+
*/
|
|
63
|
+
index: number;
|
|
54
64
|
};
|
|
65
|
+
|
|
55
66
|
/**
|
|
56
67
|
* 深度遍历的同步迭代器函数类型。
|
|
57
68
|
*
|
|
@@ -60,6 +71,7 @@ export type TTreeInfo<I extends TTreeItem> = TTreeWalker<I> & {
|
|
|
60
71
|
* @returns 如果返回 `false`,则提前终止遍历。
|
|
61
72
|
*/
|
|
62
73
|
export type TreeEachIterator<I extends TTreeItem> = (info: TTreeInfo<I>) => false | unknown;
|
|
74
|
+
|
|
63
75
|
/**
|
|
64
76
|
* 深度遍历的异步迭代器函数类型。
|
|
65
77
|
*
|
|
@@ -68,6 +80,7 @@ export type TreeEachIterator<I extends TTreeItem> = (info: TTreeInfo<I>) => fals
|
|
|
68
80
|
* @returns 如果返回 `false`,则提前终止遍历。
|
|
69
81
|
*/
|
|
70
82
|
export type TreeEachIteratorAsync<I extends TTreeItem> = (info: TTreeInfo<I>) => Promise<boolean | unknown>;
|
|
83
|
+
|
|
71
84
|
/**
|
|
72
85
|
* 深度遍历的同步遍历器函数类型。
|
|
73
86
|
*
|
|
@@ -76,6 +89,7 @@ export type TreeEachIteratorAsync<I extends TTreeItem> = (info: TTreeInfo<I>) =>
|
|
|
76
89
|
* @returns 遍历结果。
|
|
77
90
|
*/
|
|
78
91
|
export type TreeWalk<I extends TTreeItem> = (walker: TTreeWalker<I>) => unknown;
|
|
92
|
+
|
|
79
93
|
/**
|
|
80
94
|
* 深度遍历的异步遍历器函数类型。
|
|
81
95
|
*
|
|
@@ -84,6 +98,7 @@ export type TreeWalk<I extends TTreeItem> = (walker: TTreeWalker<I>) => unknown;
|
|
|
84
98
|
* @returns 异步遍历结果。
|
|
85
99
|
*/
|
|
86
100
|
export type TreeWalkAsync<I extends TTreeItem> = (walker: TTreeWalker<I>) => Promise<unknown>;
|
|
101
|
+
|
|
87
102
|
/**
|
|
88
103
|
* 深度遍历数组中的每个元素,并对每个元素执行提供的回调函数。
|
|
89
104
|
*
|
|
@@ -105,7 +120,90 @@ export type TreeWalkAsync<I extends TTreeItem> = (walker: TTreeWalker<I>) => Pro
|
|
|
105
120
|
* });
|
|
106
121
|
* ```
|
|
107
122
|
*/
|
|
108
|
-
export
|
|
123
|
+
export function treeEach<I extends TTreeItem = TTreeItem>(
|
|
124
|
+
treeList: TTreeList<I>,
|
|
125
|
+
iterator: TreeEachIterator<I>,
|
|
126
|
+
breadthFist = false,
|
|
127
|
+
): void {
|
|
128
|
+
const treeInfoList: TTreeInfo<I>[] = [];
|
|
129
|
+
let returnFalse = false;
|
|
130
|
+
|
|
131
|
+
const iterate = (info: TTreeInfo<I>) => {
|
|
132
|
+
if (iterator(info) === false) {
|
|
133
|
+
returnFalse = true;
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const next = (info: TTreeInfo<I>, walk: TreeWalk<I>) => {
|
|
139
|
+
const { item, level, parent, path } = info;
|
|
140
|
+
const { children } = item;
|
|
141
|
+
|
|
142
|
+
if (isArray(children)) {
|
|
143
|
+
returnFalse =
|
|
144
|
+
walk({
|
|
145
|
+
...info,
|
|
146
|
+
parent: item,
|
|
147
|
+
list: children as TTreeList<I>,
|
|
148
|
+
level: level + 1,
|
|
149
|
+
}) === false;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const walk: TreeWalk<I> = (walker) => {
|
|
154
|
+
const { list, level, parent, path } = walker;
|
|
155
|
+
|
|
156
|
+
const path2 = [...path];
|
|
157
|
+
while (parent !== null && path2.length > 0 && path2[path2.length - 1] !== parent) {
|
|
158
|
+
path2.pop();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
arrayEach(list, (item, index) => {
|
|
162
|
+
if (returnFalse) return false;
|
|
163
|
+
|
|
164
|
+
const info: TTreeInfo<I> = {
|
|
165
|
+
...walker,
|
|
166
|
+
item,
|
|
167
|
+
index,
|
|
168
|
+
path: [...path2, item],
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// 广度优先
|
|
172
|
+
if (breadthFist) {
|
|
173
|
+
treeInfoList.push(info);
|
|
174
|
+
}
|
|
175
|
+
// 深度优先
|
|
176
|
+
else {
|
|
177
|
+
iterate(info);
|
|
178
|
+
if (returnFalse) return false;
|
|
179
|
+
next(info, walk);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
if (breadthFist) {
|
|
184
|
+
while (!returnFalse) {
|
|
185
|
+
const info = treeInfoList.shift();
|
|
186
|
+
if (!info) break;
|
|
187
|
+
|
|
188
|
+
iterate(info);
|
|
189
|
+
if (returnFalse) break;
|
|
190
|
+
|
|
191
|
+
// 内部也会进入 walk
|
|
192
|
+
next(info, walk);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return !returnFalse;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
walk({
|
|
200
|
+
list: treeList,
|
|
201
|
+
level: 1,
|
|
202
|
+
parent: null,
|
|
203
|
+
path: [],
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
109
207
|
/**
|
|
110
208
|
* 在深度数组中查找满足条件的第一个节点信息。
|
|
111
209
|
*
|
|
@@ -133,7 +231,27 @@ export declare function treeEach<I extends TTreeItem = TTreeItem>(treeList: TTre
|
|
|
133
231
|
* // }
|
|
134
232
|
* ```
|
|
135
233
|
*/
|
|
136
|
-
export
|
|
234
|
+
export function treeFind<I extends TTreeItem>(
|
|
235
|
+
treeList: TTreeList<I>,
|
|
236
|
+
predicate: (info: TTreeInfo<I>) => boolean,
|
|
237
|
+
breadthFist = false,
|
|
238
|
+
): TTreeInfo<I> | undefined {
|
|
239
|
+
let found: TTreeInfo<I> | undefined;
|
|
240
|
+
|
|
241
|
+
treeEach(
|
|
242
|
+
treeList,
|
|
243
|
+
(info) => {
|
|
244
|
+
if (predicate(info)) {
|
|
245
|
+
found = info;
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
breadthFist,
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
return found;
|
|
253
|
+
}
|
|
254
|
+
|
|
137
255
|
/**
|
|
138
256
|
* 将深度嵌套的树形结构扁平化为一维数组,并对每个节点执行指定的转换函数。
|
|
139
257
|
*
|
|
@@ -154,18 +272,37 @@ export declare function treeFind<I extends TTreeItem>(treeList: TTreeList<I>, pr
|
|
|
154
272
|
* console.log(flattened); // [1, 2, 3, 4]
|
|
155
273
|
* ```
|
|
156
274
|
*/
|
|
157
|
-
export
|
|
275
|
+
export function deepFlat<I extends TTreeItem, T>(
|
|
276
|
+
deepList: TTreeList<I>,
|
|
277
|
+
flatten: (info: TTreeInfo<I>) => T,
|
|
278
|
+
breadthFist = false,
|
|
279
|
+
): T[] {
|
|
280
|
+
const list2: T[] = [];
|
|
281
|
+
|
|
282
|
+
treeEach(
|
|
283
|
+
deepList,
|
|
284
|
+
(info) => {
|
|
285
|
+
list2.push(flatten(info));
|
|
286
|
+
},
|
|
287
|
+
breadthFist,
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
return list2;
|
|
291
|
+
}
|
|
292
|
+
|
|
158
293
|
type FromItemInfo<I> = {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
294
|
+
selfKey: unknown;
|
|
295
|
+
parentKey: unknown;
|
|
296
|
+
item: I;
|
|
297
|
+
index: number;
|
|
163
298
|
};
|
|
299
|
+
|
|
164
300
|
export type TTreeFromOptions<I extends TTreeItem> = {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
301
|
+
getSelfKey: (item: I, index: number) => unknown;
|
|
302
|
+
getParentKey: (item: I, index: number) => unknown;
|
|
303
|
+
appendChild: (parentInfo: FromItemInfo<I>, info: FromItemInfo<I>) => unknown;
|
|
168
304
|
};
|
|
305
|
+
|
|
169
306
|
/**
|
|
170
307
|
* 从扁平列表构建树形结构。
|
|
171
308
|
*
|
|
@@ -206,5 +343,52 @@ export type TTreeFromOptions<I extends TTreeItem> = {
|
|
|
206
343
|
* // }
|
|
207
344
|
* ```
|
|
208
345
|
*/
|
|
209
|
-
export
|
|
210
|
-
|
|
346
|
+
export function treeFrom<I extends TTreeItem>(list: I[], options: TTreeFromOptions<I>): TTreeList<I> | undefined {
|
|
347
|
+
const keyMap = new Map<unknown, FromItemInfo<I>>();
|
|
348
|
+
const freeSet = new Set<FromItemInfo<I>>();
|
|
349
|
+
const roots: TTreeList<I> = [];
|
|
350
|
+
|
|
351
|
+
// 分配节点
|
|
352
|
+
const assign = (info: FromItemInfo<I>, isFirst = false) => {
|
|
353
|
+
const { selfKey, parentKey, item, index } = info;
|
|
354
|
+
|
|
355
|
+
// 父级指向为空
|
|
356
|
+
if (isNullish(parentKey)) {
|
|
357
|
+
roots.push(item);
|
|
358
|
+
}
|
|
359
|
+
// 父级指向不为空
|
|
360
|
+
else {
|
|
361
|
+
const parent = keyMap.get(parentKey);
|
|
362
|
+
|
|
363
|
+
// 未找到父级节点
|
|
364
|
+
if (isUndefined(parent)) {
|
|
365
|
+
// 游离节点
|
|
366
|
+
if (isFirst) freeSet.add(info);
|
|
367
|
+
}
|
|
368
|
+
// 已找到父级节点
|
|
369
|
+
else {
|
|
370
|
+
options.appendChild(parent, info);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
// 构建 map
|
|
376
|
+
arrayEach(list, (item, index) => {
|
|
377
|
+
const selfKey = options.getSelfKey(item, index);
|
|
378
|
+
const parentKey = options.getParentKey(item, index);
|
|
379
|
+
|
|
380
|
+
if (isNullish(selfKey)) return;
|
|
381
|
+
|
|
382
|
+
const info = { selfKey, parentKey, item, index };
|
|
383
|
+
keyMap.set(selfKey, info);
|
|
384
|
+
|
|
385
|
+
assign(info, true);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// 处理游离节点
|
|
389
|
+
for (const info of freeSet.values()) {
|
|
390
|
+
assign(info);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return roots;
|
|
394
|
+
}
|
|
@@ -1,93 +1,158 @@
|
|
|
1
|
-
import { AnyArray, AnyAsyncFunction, AnyFunction, AnyObject } from './types';
|
|
1
|
+
import type { AnyArray, AnyAsyncFunction, AnyFunction, AnyObject } from './types';
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
4
|
* 获取未知类型的类型名称
|
|
4
5
|
* @param unknown - 未知类型的值
|
|
5
6
|
* @returns 类型名称字符串
|
|
6
7
|
*/
|
|
7
|
-
export
|
|
8
|
+
export function typeIs(
|
|
9
|
+
unknown: unknown,
|
|
10
|
+
):
|
|
11
|
+
| 'string'
|
|
12
|
+
| 'number'
|
|
13
|
+
| 'boolean'
|
|
14
|
+
| 'object'
|
|
15
|
+
| 'array'
|
|
16
|
+
| 'function'
|
|
17
|
+
| 'null'
|
|
18
|
+
| 'undefined'
|
|
19
|
+
| 'symbol'
|
|
20
|
+
| 'bigint'
|
|
21
|
+
| 'error'
|
|
22
|
+
| 'promise'
|
|
23
|
+
| string {
|
|
24
|
+
return Object.prototype.toString.call(unknown).slice(8, -1).toLowerCase();
|
|
25
|
+
}
|
|
26
|
+
|
|
8
27
|
/**
|
|
9
28
|
* 检查值是否为字符串
|
|
10
29
|
* @param unknown - 未知类型的值
|
|
11
30
|
* @returns 如果值为字符串则返回 true,否则返回 false
|
|
12
31
|
*/
|
|
13
|
-
export
|
|
32
|
+
export function isString(unknown: unknown): unknown is string {
|
|
33
|
+
return typeof unknown === 'string';
|
|
34
|
+
}
|
|
35
|
+
|
|
14
36
|
/**
|
|
15
37
|
* 检查值是否为布尔值
|
|
16
38
|
* @param unknown - 未知类型的值
|
|
17
39
|
* @returns 如果值为布尔值则返回 true,否则返回 false
|
|
18
40
|
*/
|
|
19
|
-
export
|
|
41
|
+
export function isBoolean(unknown: unknown): unknown is boolean {
|
|
42
|
+
return typeof unknown === 'boolean';
|
|
43
|
+
}
|
|
44
|
+
|
|
20
45
|
/**
|
|
21
46
|
* 检查值是否为符号
|
|
22
47
|
* @param unknown - 未知类型的值
|
|
23
48
|
* @returns 如果值为符号则返回 true,否则返回 false
|
|
24
49
|
*/
|
|
25
|
-
export
|
|
50
|
+
export function isSymbol(unknown: unknown): unknown is symbol {
|
|
51
|
+
return typeof unknown === 'symbol';
|
|
52
|
+
}
|
|
53
|
+
|
|
26
54
|
/**
|
|
27
55
|
* 检查值是否为大整数
|
|
28
56
|
* @param unknown - 未知类型的值
|
|
29
57
|
* @returns 如果值为大整数则返回 true,否则返回 false
|
|
30
58
|
*/
|
|
31
|
-
export
|
|
59
|
+
export function isBigInt(unknown: unknown): unknown is bigint {
|
|
60
|
+
return typeof unknown === 'bigint';
|
|
61
|
+
}
|
|
62
|
+
|
|
32
63
|
/**
|
|
33
64
|
* 检查值是否为数字
|
|
34
65
|
* @param unknown - 未知类型的值
|
|
35
66
|
* @returns 如果值为数字且不是 NaN 则返回 true,否则返回 false
|
|
36
67
|
*/
|
|
37
|
-
export
|
|
68
|
+
export function isNumber(unknown: unknown): unknown is number {
|
|
69
|
+
return typeof unknown === 'number' && !Number.isNaN(unknown);
|
|
70
|
+
}
|
|
71
|
+
|
|
38
72
|
/**
|
|
39
73
|
* 检查值是否为 undefined
|
|
40
74
|
* @param unknown - 未知类型的值
|
|
41
75
|
* @returns 如果值为 undefined 则返回 true,否则返回 false
|
|
42
76
|
*/
|
|
43
|
-
export
|
|
77
|
+
export function isUndefined(unknown: unknown): unknown is undefined {
|
|
78
|
+
return typeof unknown === 'undefined';
|
|
79
|
+
}
|
|
80
|
+
|
|
44
81
|
/**
|
|
45
82
|
* 检查值是否为 void
|
|
46
83
|
* @param unknown - 未知类型的值
|
|
47
84
|
* @returns 如果值为 undefined 则返回 true,否则返回 false
|
|
48
85
|
*/
|
|
49
|
-
|
|
86
|
+
// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>
|
|
87
|
+
export function isVoid(unknown: unknown): unknown is void {
|
|
88
|
+
return isUndefined(unknown);
|
|
89
|
+
}
|
|
90
|
+
|
|
50
91
|
/**
|
|
51
92
|
* 永不执行,用于 switch-case/if-else 类型断言
|
|
52
93
|
* @param unknown - 永远不会执行的值
|
|
53
94
|
*/
|
|
54
|
-
export
|
|
95
|
+
export function isNever(unknown: never) {
|
|
96
|
+
//
|
|
97
|
+
}
|
|
98
|
+
|
|
55
99
|
/**
|
|
56
100
|
* 检查值是否为 null
|
|
57
101
|
* @param unknown - 未知类型的值
|
|
58
102
|
* @returns 如果值为 null 则返回 true,否则返回 false
|
|
59
103
|
*/
|
|
60
|
-
export
|
|
104
|
+
export function isNull(unknown: unknown): unknown is null {
|
|
105
|
+
return unknown === null;
|
|
106
|
+
}
|
|
107
|
+
|
|
61
108
|
/**
|
|
62
109
|
* 检查值是否为 nullish(null 或 undefined 或 void)
|
|
63
110
|
* @param unknown - 未知类型的值
|
|
64
111
|
* @returns 如果值为 null 或 undefined 或 void 则返回 true,否则返回 false
|
|
65
112
|
*/
|
|
66
|
-
|
|
113
|
+
// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>
|
|
114
|
+
export function isNullish(unknown: unknown): unknown is null | undefined | void {
|
|
115
|
+
return isNull(unknown) || isUndefined(unknown) || isVoid(unknown);
|
|
116
|
+
}
|
|
117
|
+
|
|
67
118
|
/**
|
|
68
119
|
* 检查值是否为原始类型(null 或 非对象)
|
|
69
120
|
* @param unknown - 未知类型的值
|
|
70
121
|
* @returns 如果值为原始类型则返回 true,否则返回 false
|
|
71
122
|
*/
|
|
72
|
-
export
|
|
123
|
+
export function isPrimitive(
|
|
124
|
+
unknown: unknown,
|
|
125
|
+
): unknown is string | number | boolean | symbol | bigint | null | undefined {
|
|
126
|
+
return isNull(unknown) || !(typeof unknown === 'object' || typeof unknown === 'function');
|
|
127
|
+
}
|
|
128
|
+
|
|
73
129
|
/**
|
|
74
130
|
* 检查值是否为对象,但要注意,此时的对象类型是包含了数组和函数
|
|
75
131
|
* @param unknown - 未知类型的值
|
|
76
132
|
* @returns 如果值为对象则返回 true,否则返回 false
|
|
77
133
|
*/
|
|
78
|
-
export
|
|
134
|
+
export function isObject(unknown: unknown): unknown is AnyObject {
|
|
135
|
+
return typeIs(unknown) === 'object';
|
|
136
|
+
}
|
|
137
|
+
|
|
79
138
|
/**
|
|
80
139
|
* 检查值是否为数组
|
|
81
140
|
* @param unknown - 未知类型的值
|
|
82
141
|
* @returns 如果值为数组则返回 true,否则返回 false
|
|
83
142
|
*/
|
|
84
|
-
export
|
|
143
|
+
export function isArray(unknown: unknown): unknown is AnyArray {
|
|
144
|
+
return Array.isArray(unknown);
|
|
145
|
+
}
|
|
146
|
+
|
|
85
147
|
/**
|
|
86
148
|
* 检查值是否为函数
|
|
87
149
|
* @param unknown - 未知类型的值
|
|
88
150
|
* @returns 如果值为函数则返回 true,否则返回 false
|
|
89
151
|
*/
|
|
90
|
-
export
|
|
152
|
+
export function isFunction(unknown: unknown): unknown is AnyFunction {
|
|
153
|
+
return typeof unknown === 'function';
|
|
154
|
+
}
|
|
155
|
+
|
|
91
156
|
/**
|
|
92
157
|
* 检查值是否为异步函数
|
|
93
158
|
* @param unknown - 需要检查的值
|
|
@@ -100,22 +165,33 @@ export declare function isFunction(unknown: unknown): unknown is AnyFunction;
|
|
|
100
165
|
* isAsyncFunction(() => {}); // false
|
|
101
166
|
* ```
|
|
102
167
|
*/
|
|
103
|
-
export
|
|
168
|
+
export function isAsyncFunction(unknown: unknown): unknown is AnyAsyncFunction {
|
|
169
|
+
return isFunction(unknown) && unknown.constructor.name === 'AsyncFunction';
|
|
170
|
+
}
|
|
171
|
+
|
|
104
172
|
/**
|
|
105
173
|
* 检查值是否为 Error 类型
|
|
106
174
|
* @param unknown - 未知类型的值
|
|
107
175
|
* @returns 如果值为 Error 类型则返回 true,否则返回 false
|
|
108
176
|
*/
|
|
109
|
-
export
|
|
177
|
+
export function isError(unknown: unknown): unknown is Error {
|
|
178
|
+
return unknown instanceof Error;
|
|
179
|
+
}
|
|
180
|
+
|
|
110
181
|
/**
|
|
111
182
|
* 检查值是否为 Promise 类型
|
|
112
183
|
* @param unknown - 未知类型的值
|
|
113
184
|
* @returns 如果值为 Promise 类型则返回 true,否则返回 false
|
|
114
185
|
*/
|
|
115
|
-
export
|
|
186
|
+
export function isPromise<T>(unknown: unknown): unknown is Promise<T> {
|
|
187
|
+
return typeIs(unknown) === 'promise';
|
|
188
|
+
}
|
|
189
|
+
|
|
116
190
|
/**
|
|
117
191
|
* 检查值是否为 Date 类型
|
|
118
192
|
* @param unknown - 未知类型的值
|
|
119
193
|
* @returns 如果值为 Date 类型则返回 true,否则返回 false
|
|
120
194
|
*/
|
|
121
|
-
export
|
|
195
|
+
export function isDate(unknown: unknown): unknown is Date {
|
|
196
|
+
return unknown instanceof Date;
|
|
197
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* 任意对象
|
|
3
3
|
*/
|
|
4
4
|
export type AnyObject = Record<PropertyKey, unknown>;
|
|
5
|
+
|
|
5
6
|
/**
|
|
6
7
|
* 返回对象的所有键名,并且键名都是字符串类型
|
|
7
8
|
* @example
|
|
@@ -10,48 +11,68 @@ export type AnyObject = Record<PropertyKey, unknown>;
|
|
|
10
11
|
* // 'a' | '2'
|
|
11
12
|
* ```
|
|
12
13
|
*/
|
|
13
|
-
export type KeysOf<T> = {
|
|
14
|
-
|
|
15
|
-
}[keyof T];
|
|
14
|
+
export type KeysOf<T> = { [P in keyof T]: P extends string ? P : P extends number ? `${P}` : never }[keyof T];
|
|
15
|
+
|
|
16
16
|
/**
|
|
17
17
|
* 任意数组
|
|
18
18
|
*/
|
|
19
19
|
export type AnyArray = Array<unknown>;
|
|
20
|
+
|
|
20
21
|
/**
|
|
21
22
|
* 任意函数
|
|
22
23
|
*/
|
|
24
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
23
25
|
export type AnyFunction = (...args: any[]) => any;
|
|
26
|
+
|
|
24
27
|
/**
|
|
25
28
|
* 任意异步函数
|
|
26
29
|
*/
|
|
30
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
27
31
|
export type AnyAsyncFunction = (...args: any[]) => Promise<any>;
|
|
32
|
+
|
|
28
33
|
/**
|
|
29
34
|
* 可能是 Promise 的类型
|
|
30
35
|
*/
|
|
31
36
|
export type MaybePromise<T> = T | Promise<T>;
|
|
37
|
+
|
|
32
38
|
/**
|
|
33
39
|
* 可能是可执行的类型
|
|
34
40
|
*/
|
|
35
41
|
export type MaybeCallable<T> = T | (() => T);
|
|
42
|
+
|
|
36
43
|
/**
|
|
37
44
|
* 深度部分类型
|
|
38
45
|
*/
|
|
39
|
-
export type DeepPartial<T> = T extends object ? {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
export type DeepPartial<T> = T extends object ? { [P in keyof T]?: DeepPartial<T[P]> } : T;
|
|
47
|
+
|
|
48
|
+
// https://juejin.cn/post/6994102811218673700#heading-24
|
|
49
|
+
|
|
50
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
51
|
+
export type UnionToIntersection<T> = (T extends any ? (arg: T) => void : never) extends (arg: infer U) => void
|
|
52
|
+
? U
|
|
53
|
+
: never;
|
|
54
|
+
// type T0 = UnionToIntersection<{ key1: string } | { key2: number }>;
|
|
55
|
+
|
|
43
56
|
/**
|
|
44
57
|
* 从联合类型中提取最后一个类型
|
|
45
58
|
* @template U - 联合类型
|
|
46
59
|
*/
|
|
47
60
|
type _UnionLast<U> = UnionToIntersection<U extends U ? (x: U) => 0 : never> extends (x: infer L) => 0 ? L : never;
|
|
61
|
+
|
|
48
62
|
/**
|
|
49
63
|
* 将联合类型转换为元组类型
|
|
50
64
|
* @template U - 联合类型
|
|
51
65
|
* @template Last - 联合类型中的最后一个类型
|
|
52
66
|
*/
|
|
53
|
-
export type UnionToTuple<U, Last = _UnionLast<U>> = [U] extends [never]
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
export type UnionToTuple<U, Last = _UnionLast<U>> = [U] extends [never]
|
|
68
|
+
? []
|
|
69
|
+
: [...UnionToTuple<Exclude<U, Last>>, Last];
|
|
70
|
+
|
|
71
|
+
// type T2 = LastInUnion<'a' | 'b' | 'c' | 'd'>;
|
|
72
|
+
// type T3 = UnionToTuple<'a' | 'b' | 'c' | 'd'>;
|
|
73
|
+
// ['a', 'b', 'c', 'd']
|
|
74
|
+
|
|
75
|
+
// https://juejin.cn/post/7187963986875252795#heading-4
|
|
76
|
+
// type Merged = MergeIntersection<{ a: string } & { b: number }>;
|
|
77
|
+
// { a: string; b: number }
|
|
78
|
+
export type MergeIntersection<A> = A extends infer T ? { [Key in keyof T]: T[Key] } : never;
|