@movk/core 0.0.5 → 1.0.0
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/README.md +98 -147
- package/dist/index.d.mts +1133 -596
- package/dist/index.d.ts +1133 -596
- package/dist/index.mjs +1 -1
- package/package.json +32 -35
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { VNode, Ref } from 'vue';
|
|
1
|
+
import { MaybeRefOrGetter, VNode, Ref, Component, DefineComponent } from 'vue';
|
|
2
2
|
import { z } from 'zod/v4';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -29,6 +29,37 @@ type ApiUnwrapPromise<T> = T extends Promise<infer U> ? U : T;
|
|
|
29
29
|
*/
|
|
30
30
|
type ApiAwaitedReturn<TFn> = TFn extends (...args: any[]) => ApiAwaitable<infer R> ? R : never;
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* 提供字符串字面量提示的同时允许任意字符串
|
|
34
|
+
* 在 IDE 中提供 T 类型的自动补全提示,但不限制只能使用这些值
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* type Color = Suggest<'red' | 'blue' | 'green'>
|
|
39
|
+
*
|
|
40
|
+
* // IDE 会提示 'red', 'blue', 'green',但也可以使用其他字符串
|
|
41
|
+
* const color1: Color = 'red' // 有提示
|
|
42
|
+
* const color2: Color = 'yellow' // 也可以,虽然没有提示
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
type Suggest<T extends string> = T | (string & {});
|
|
46
|
+
/**
|
|
47
|
+
* 响应式值类型 - 基于 Vue 的 `MaybeRefOrGetter` 扩展,额外支持上下文回调
|
|
48
|
+
*
|
|
49
|
+
* @template T - 值类型
|
|
50
|
+
* @template CTX - 上下文类型(用于回调函数)
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* const value: ReactiveValue<boolean> = ref(false)
|
|
55
|
+
* const getter: ReactiveValue<string> = () => name.value
|
|
56
|
+
* const computed: ReactiveValue<number> = computed(() => count.value)
|
|
57
|
+
* const withContext: ReactiveValue<boolean, Context> = (ctx) => ctx.value > 0
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
type ReactiveValue<T, CTX = never> = [CTX] extends [never] ? MaybeRefOrGetter<T> : MaybeRefOrGetter<T> | ((ctx: CTX) => T);
|
|
61
|
+
type StripNullable<T> = T extends null | undefined ? never : T;
|
|
62
|
+
|
|
32
63
|
type UnknownObject = Record<string, unknown>;
|
|
33
64
|
type AnyObject = Record<string, any>;
|
|
34
65
|
/**
|
|
@@ -176,6 +207,125 @@ type GetObjectField<MaybeObject, Key extends string> = MaybeObject extends Recor
|
|
|
176
207
|
* // - () => h('div', '标题') 的惰性渲染函数
|
|
177
208
|
*/
|
|
178
209
|
type StringOrVNode = string | VNode | (() => VNode);
|
|
210
|
+
/**
|
|
211
|
+
* 合并两个对象类型,U 中的属性会覆盖 T 中的属性
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```ts
|
|
215
|
+
* type T = { a: number, c: string }
|
|
216
|
+
* type U = { a: string, b: boolean }
|
|
217
|
+
* type M = Merge<T, U> // { a: string, b: boolean, c: string }
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
type Merge<T, U> = Omit<T, keyof U> & U;
|
|
221
|
+
/**
|
|
222
|
+
* 判断类型 T 是否为纯对象类型
|
|
223
|
+
* 纯对象是指普通的对象字面量,排除数组、函数、Date 等特殊对象类型
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* type Test1 = IsPlainObject<{ a: number }> // true
|
|
227
|
+
* type Test2 = IsPlainObject<string[]> // false
|
|
228
|
+
* type Test3 = IsPlainObject<() => void> // false
|
|
229
|
+
* type Test4 = IsPlainObject<Date> // false
|
|
230
|
+
* type Test5 = IsPlainObject<string> // false
|
|
231
|
+
* type Test6 = IsPlainObject<null> // false
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
type IsPlainObject<T> = (T extends null | undefined ? never : T) extends Record<string, any> ? (T extends null | undefined ? never : T) extends any[] ? false : (T extends null | undefined ? never : T) extends (...args: any[]) => any ? false : (T extends null | undefined ? never : T) extends Date ? false : true : false;
|
|
235
|
+
/**
|
|
236
|
+
* 深度控制类型,用于限制类型递归的深度
|
|
237
|
+
* 防止类型计算超出 TypeScript 的递归限制
|
|
238
|
+
*/
|
|
239
|
+
type Depth = [never, 0, 1, 2, 3, 4];
|
|
240
|
+
/**
|
|
241
|
+
* 提取对象的嵌套键,支持点语法路径
|
|
242
|
+
*
|
|
243
|
+
* @template T 源对象类型
|
|
244
|
+
* @template D 递归深度,默认为2
|
|
245
|
+
* @example
|
|
246
|
+
* ```ts
|
|
247
|
+
* type User = {
|
|
248
|
+
* name: string
|
|
249
|
+
* address: {
|
|
250
|
+
* city: string
|
|
251
|
+
* country: string
|
|
252
|
+
* }
|
|
253
|
+
* }
|
|
254
|
+
* type Keys = NestedKeys<User> // 'name' | 'address' | 'address.city' | 'address.country'
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
type NestedKeys<T, D extends number = 2> = [D] extends [never] ? never : {
|
|
258
|
+
[K in keyof T & string]: IsPlainObject<T[K]> extends true ? K | `${K}.${NestedKeys<T[K] extends null | undefined ? never : T[K], Depth[D]>}` : K;
|
|
259
|
+
}[keyof T & string];
|
|
260
|
+
/**
|
|
261
|
+
* 提取对象中所有纯对象字段的键(包括嵌套的),支持点语法路径
|
|
262
|
+
*
|
|
263
|
+
* @template T 源对象类型
|
|
264
|
+
* @template D 递归深度,默认为2
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* type User = {
|
|
268
|
+
* name: string
|
|
269
|
+
* age: number
|
|
270
|
+
* address: {
|
|
271
|
+
* city: string
|
|
272
|
+
* location: {
|
|
273
|
+
* lat: number
|
|
274
|
+
* lng: number
|
|
275
|
+
* }
|
|
276
|
+
* }
|
|
277
|
+
* }
|
|
278
|
+
* type ObjectKeys = ObjectFieldKeys<User> // 'address' | 'address.location'
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
type ObjectFieldKeys<T, D extends number = 2> = [D] extends [never] ? never : {
|
|
282
|
+
[K in keyof T & string]: IsPlainObject<T[K]> extends true ? K | `${K}.${ObjectFieldKeys<T[K] extends null | undefined ? never : T[K], Depth[D]>}` : never;
|
|
283
|
+
}[keyof T & string];
|
|
284
|
+
/**
|
|
285
|
+
* 提取对象中所有非对象字段的键
|
|
286
|
+
* 排除纯对象字段,只保留原始类型字段的键
|
|
287
|
+
*
|
|
288
|
+
* @template T 源对象类型
|
|
289
|
+
* @example
|
|
290
|
+
* ```ts
|
|
291
|
+
* type User = {
|
|
292
|
+
* name: string
|
|
293
|
+
* age: number
|
|
294
|
+
* address: {
|
|
295
|
+
* city: string
|
|
296
|
+
* }
|
|
297
|
+
* }
|
|
298
|
+
* type NonObjectKeys = NonObjectFieldKeys<User> // 'name' | 'age' | 'address.city'
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
type NonObjectFieldKeys<T> = Exclude<NestedKeys<T>, ObjectFieldKeys<T>>;
|
|
302
|
+
/**
|
|
303
|
+
* 提取对象中所有数组字段的键(包括嵌套的),支持点语法路径
|
|
304
|
+
*
|
|
305
|
+
* @template T 源对象类型
|
|
306
|
+
* @template D 递归深度,默认为2
|
|
307
|
+
* @example
|
|
308
|
+
* ```ts
|
|
309
|
+
* type User = {
|
|
310
|
+
* name: string
|
|
311
|
+
* tags: string[]
|
|
312
|
+
* posts: Array<{ title: string }>
|
|
313
|
+
* profile: {
|
|
314
|
+
* hobbies: string[]
|
|
315
|
+
* }
|
|
316
|
+
* }
|
|
317
|
+
* type ArrayKeys = ArrayFieldKeys<User> // 'tags' | 'posts' | 'profile.hobbies'
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
type ArrayFieldKeys<T, D extends number = 2> = [D] extends [never] ? never : {
|
|
321
|
+
[K in keyof T & string]: (T[K] extends null | undefined ? never : T[K]) extends any[] ? K : IsPlainObject<T[K]> extends true ? `${K}.${ArrayFieldKeys<T[K] extends null | undefined ? never : T[K], Depth[D]>}` : never;
|
|
322
|
+
}[keyof T & string];
|
|
323
|
+
/**
|
|
324
|
+
* 根据路径字符串提取对象属性的类型,支持点语法和嵌套对象
|
|
325
|
+
* @example GetFieldValue<User, 'tags'> // string[]
|
|
326
|
+
* @example GetFieldValue<User, 'profile.bio'> // string
|
|
327
|
+
*/
|
|
328
|
+
type GetFieldValue<T, P extends string> = P extends keyof T ? T[P] : P extends `${infer K}.${infer Rest}` ? K extends keyof T ? T[K] extends undefined ? undefined : GetFieldValue<NonNullable<T[K]>, Rest> : unknown : unknown;
|
|
179
329
|
|
|
180
330
|
declare const StorageTypeSchema: z.ZodEnum<{
|
|
181
331
|
localStorage: "localStorage";
|
|
@@ -201,6 +351,38 @@ interface AppStorageReturn<T> {
|
|
|
201
351
|
removeItem: () => void;
|
|
202
352
|
}
|
|
203
353
|
|
|
354
|
+
/**
|
|
355
|
+
* vue-component-type-helpers
|
|
356
|
+
* Copy from https://github.com/vuejs/language-tools/tree/master/packages/component-type-helpers
|
|
357
|
+
*/
|
|
358
|
+
type IsComponent = StringOrVNode | Component | DefineComponent | ((...args: any[]) => any);
|
|
359
|
+
type ComponentType<T> = T extends new (...args: any) => {} ? 1 : T extends (...args: any) => any ? 2 : 0;
|
|
360
|
+
type ComponentProps<T> = T extends new (...args: any) => {
|
|
361
|
+
$props: infer P;
|
|
362
|
+
} ? NonNullable<P> : T extends (props: infer P, ...args: any) => any ? P : {};
|
|
363
|
+
type ComponentSlots<T> = T extends new (...args: any) => {
|
|
364
|
+
$slots: infer S;
|
|
365
|
+
} ? NonNullable<S> : T extends (props: any, ctx: {
|
|
366
|
+
slots: infer S;
|
|
367
|
+
attrs: any;
|
|
368
|
+
emit: any;
|
|
369
|
+
}, ...args: any) => any ? NonNullable<S> : {};
|
|
370
|
+
type ComponentAttrs<T> = T extends new (...args: any) => {
|
|
371
|
+
$attrs: infer A;
|
|
372
|
+
} ? NonNullable<A> : T extends (props: any, ctx: {
|
|
373
|
+
slots: any;
|
|
374
|
+
attrs: infer A;
|
|
375
|
+
emit: any;
|
|
376
|
+
}, ...args: any) => any ? NonNullable<A> : {};
|
|
377
|
+
type ComponentEmit<T> = T extends new (...args: any) => {
|
|
378
|
+
$emit: infer E;
|
|
379
|
+
} ? NonNullable<E> : T extends (props: any, ctx: {
|
|
380
|
+
slots: any;
|
|
381
|
+
attrs: any;
|
|
382
|
+
emit: infer E;
|
|
383
|
+
}, ...args: any) => any ? NonNullable<E> : {};
|
|
384
|
+
type ComponentExposed<T> = T extends new (...args: any) => infer E ? E : T extends (props: any, ctx: any, expose: (exposed: infer E) => any, ...args: any) => any ? NonNullable<E> : {};
|
|
385
|
+
|
|
204
386
|
/**
|
|
205
387
|
* 应用存储管理的组合式函数,支持localStorage和sessionStorage
|
|
206
388
|
*
|
|
@@ -284,532 +466,130 @@ declare function useAppStorage<T = unknown>(config: StorageConfigInput<T>): AppS
|
|
|
284
466
|
*/
|
|
285
467
|
declare function useCopyCode(text: string): Promise<boolean>;
|
|
286
468
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
* ]
|
|
412
|
-
*
|
|
413
|
-
* const result = Tree.find(tree, (node) => node.name === '部门1-1')
|
|
414
|
-
* console.log(result?.node.id) // '2'
|
|
415
|
-
* console.log(result?.depth) // 1
|
|
416
|
-
* ```
|
|
417
|
-
*/
|
|
418
|
-
static find<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNodeResult<T> | undefined;
|
|
419
|
-
/**
|
|
420
|
-
* 查找树中所有满足条件的节点
|
|
421
|
-
*
|
|
422
|
-
* @category Data Structures
|
|
423
|
-
* @param tree 树形结构(单个节点或节点数组)
|
|
424
|
-
* @param predicate 查找条件函数
|
|
425
|
-
* @param config 树形配置选项
|
|
426
|
-
* @returns 所有匹配的节点结果数组,每个结果包含节点、路径、深度和索引信息
|
|
427
|
-
* @example
|
|
428
|
-
* ```ts
|
|
429
|
-
* const tree = [
|
|
430
|
-
* {
|
|
431
|
-
* id: '1',
|
|
432
|
-
* type: 'folder',
|
|
433
|
-
* name: '根目录',
|
|
434
|
-
* children: [
|
|
435
|
-
* { id: '2', type: 'file', name: '文件1', children: [] },
|
|
436
|
-
* { id: '3', type: 'file', name: '文件2', children: [] }
|
|
437
|
-
* ]
|
|
438
|
-
* }
|
|
439
|
-
* ]
|
|
440
|
-
*
|
|
441
|
-
* const files = Tree.findAll(tree, (node) => node.type === 'file')
|
|
442
|
-
* console.log(files.length) // 2
|
|
443
|
-
* ```
|
|
444
|
-
*/
|
|
445
|
-
static findAll<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNodeResult<T>[];
|
|
446
|
-
/**
|
|
447
|
-
* 根据ID查找树中的节点
|
|
448
|
-
*
|
|
449
|
-
* @category Data Structures
|
|
450
|
-
* @param tree 树形结构(单个节点或节点数组)
|
|
451
|
-
* @param id 要查找的节点ID
|
|
452
|
-
* @param config 树形配置选项
|
|
453
|
-
* @returns 匹配的节点结果,包含节点、路径、深度和索引信息;未找到时返回undefined
|
|
454
|
-
* @example
|
|
455
|
-
* ```ts
|
|
456
|
-
* const tree = [
|
|
457
|
-
* {
|
|
458
|
-
* id: '1',
|
|
459
|
-
* name: '根节点',
|
|
460
|
-
* children: [
|
|
461
|
-
* { id: '2', name: '子节点', children: [] }
|
|
462
|
-
* ]
|
|
463
|
-
* }
|
|
464
|
-
* ]
|
|
465
|
-
*
|
|
466
|
-
* const result = Tree.findById(tree, '2')
|
|
467
|
-
* console.log(result?.node.name) // '子节点'
|
|
468
|
-
* ```
|
|
469
|
-
*/
|
|
470
|
-
static findById<T = any>(tree: TreeNode<T> | TreeNode<T>[], id: string, config?: TreeConfigInput): TreeNodeResult<T> | undefined;
|
|
471
|
-
/**
|
|
472
|
-
* 获取树形结构的统计信息
|
|
473
|
-
*
|
|
474
|
-
* @category Data Structures
|
|
475
|
-
* @param tree 树形结构(单个节点或节点数组)
|
|
476
|
-
* @param config 树形配置选项
|
|
477
|
-
* @returns 树的统计信息,包含总节点数、叶子节点数、最大深度和分支节点数
|
|
478
|
-
* @example
|
|
479
|
-
* ```ts
|
|
480
|
-
* const tree = [
|
|
481
|
-
* {
|
|
482
|
-
* id: '1',
|
|
483
|
-
* name: '根节点',
|
|
484
|
-
* children: [
|
|
485
|
-
* { id: '2', name: '子节点1', children: [] },
|
|
486
|
-
* { id: '3', name: '子节点2', children: [
|
|
487
|
-
* { id: '4', name: '孙节点', children: [] }
|
|
488
|
-
* ] }
|
|
489
|
-
* ]
|
|
490
|
-
* }
|
|
491
|
-
* ]
|
|
492
|
-
*
|
|
493
|
-
* const stats = Tree.getStats(tree)
|
|
494
|
-
* console.log(stats) // { total: 4, leaves: 2, depth: 3, branches: 2 }
|
|
495
|
-
* ```
|
|
496
|
-
*/
|
|
497
|
-
static getStats<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): TreeStats;
|
|
498
|
-
/**
|
|
499
|
-
* 过滤树形结构,保留满足条件的节点及其祖先和后代
|
|
500
|
-
*
|
|
501
|
-
* @category Data Structures
|
|
502
|
-
* @param tree 树形结构(单个节点或节点数组)
|
|
503
|
-
* @param predicate 过滤条件函数
|
|
504
|
-
* @param config 树形配置选项
|
|
505
|
-
* @returns 过滤后的树形结构数组
|
|
506
|
-
* @example
|
|
507
|
-
* ```ts
|
|
508
|
-
* const tree = [
|
|
509
|
-
* {
|
|
510
|
-
* id: '1',
|
|
511
|
-
* type: 'folder',
|
|
512
|
-
* name: '根目录',
|
|
513
|
-
* children: [
|
|
514
|
-
* { id: '2', type: 'file', name: '文档.txt', children: [] },
|
|
515
|
-
* { id: '3', type: 'folder', name: '子目录', children: [
|
|
516
|
-
* { id: '4', type: 'file', name: '图片.jpg', children: [] }
|
|
517
|
-
* ] }
|
|
518
|
-
* ]
|
|
519
|
-
* }
|
|
520
|
-
* ]
|
|
521
|
-
*
|
|
522
|
-
* const filtered = Tree.filter(tree, (node) => node.type === 'file')
|
|
523
|
-
* // 返回包含所有文件节点及其父级路径的树结构
|
|
524
|
-
* ```
|
|
525
|
-
*/
|
|
526
|
-
static filter<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNode<T>[];
|
|
527
|
-
/**
|
|
528
|
-
* 转换树形结构,将每个节点转换为新的结构
|
|
529
|
-
*
|
|
530
|
-
* @category Data Structures
|
|
531
|
-
* @param tree 树形结构(单个节点或节点数组)
|
|
532
|
-
* @param transformer 节点转换函数
|
|
533
|
-
* @param config 树形配置选项
|
|
534
|
-
* @returns 转换后的树形结构数组
|
|
535
|
-
* @example
|
|
536
|
-
* ```ts
|
|
537
|
-
* const tree = [
|
|
538
|
-
* {
|
|
539
|
-
* id: '1',
|
|
540
|
-
* name: '部门1',
|
|
541
|
-
* children: [
|
|
542
|
-
* { id: '2', name: '部门1-1', children: [] }
|
|
543
|
-
* ]
|
|
544
|
-
* }
|
|
545
|
-
* ]
|
|
546
|
-
*
|
|
547
|
-
* const transformed = Tree.transform(tree, (node, depth) => ({
|
|
548
|
-
* key: node.id,
|
|
549
|
-
* title: node.name,
|
|
550
|
-
* level: depth
|
|
551
|
-
* }))
|
|
552
|
-
* // 转换为新的数据结构
|
|
553
|
-
* ```
|
|
554
|
-
*/
|
|
555
|
-
static transform<T = any, R = any>(tree: TreeNode<T> | TreeNode<T>[], transformer: TreeTransformer<T, R>, config?: TreeConfigInput): TreeNode<R>[];
|
|
556
|
-
/**
|
|
557
|
-
* 遍历树形结构的每个节点
|
|
558
|
-
*
|
|
559
|
-
* @category Data Structures
|
|
560
|
-
* @param tree 树形结构(单个节点或节点数组)
|
|
561
|
-
* @param visitor 访问者函数,返回false可以跳过子节点的遍历
|
|
562
|
-
* @param config 树形配置选项
|
|
563
|
-
* @example
|
|
564
|
-
* ```ts
|
|
565
|
-
* const tree = [
|
|
566
|
-
* {
|
|
567
|
-
* id: '1',
|
|
568
|
-
* name: '根节点',
|
|
569
|
-
* children: [
|
|
570
|
-
* { id: '2', name: '子节点', children: [] }
|
|
571
|
-
* ]
|
|
572
|
-
* }
|
|
573
|
-
* ]
|
|
574
|
-
*
|
|
575
|
-
* Tree.forEach(tree, (node, depth) => {
|
|
576
|
-
* console.log(`${' '.repeat(depth * 2)}${node.name}`)
|
|
577
|
-
* // 输出缩进的树结构
|
|
578
|
-
* })
|
|
579
|
-
* ```
|
|
580
|
-
*/
|
|
581
|
-
static forEach<T = any>(tree: TreeNode<T> | TreeNode<T>[], visitor: TreeVisitor<T>, config?: TreeConfigInput): void;
|
|
582
|
-
/**
|
|
583
|
-
* 在指定节点前插入新节点
|
|
584
|
-
*
|
|
585
|
-
* @category Data Structures
|
|
586
|
-
* @param tree 树形结构数组
|
|
587
|
-
* @param targetId 目标节点的ID
|
|
588
|
-
* @param newNode 要插入的新节点数据
|
|
589
|
-
* @param config 树形配置选项
|
|
590
|
-
* @returns 是否成功插入
|
|
591
|
-
* @example
|
|
592
|
-
* ```ts
|
|
593
|
-
* const tree = [
|
|
594
|
-
* {
|
|
595
|
-
* id: '1',
|
|
596
|
-
* name: '节点1',
|
|
597
|
-
* children: [
|
|
598
|
-
* { id: '2', name: '节点2', children: [] }
|
|
599
|
-
* ]
|
|
600
|
-
* }
|
|
601
|
-
* ]
|
|
602
|
-
*
|
|
603
|
-
* const success = Tree.insertBefore(tree, '2', { id: '1.5', name: '新节点' })
|
|
604
|
-
* console.log(success) // true
|
|
605
|
-
* ```
|
|
606
|
-
*/
|
|
607
|
-
static insertBefore<T = any>(tree: TreeNode<T>[], targetId: string, newNode: T, config?: TreeConfigInput): boolean;
|
|
608
|
-
/**
|
|
609
|
-
* 在指定节点后插入新节点
|
|
610
|
-
*
|
|
611
|
-
* @category Data Structures
|
|
612
|
-
* @param tree 树形结构数组
|
|
613
|
-
* @param targetId 目标节点的ID
|
|
614
|
-
* @param newNode 要插入的新节点数据
|
|
615
|
-
* @param config 树形配置选项
|
|
616
|
-
* @returns 是否成功插入
|
|
617
|
-
* @example
|
|
618
|
-
* ```ts
|
|
619
|
-
* const tree = [
|
|
620
|
-
* {
|
|
621
|
-
* id: '1',
|
|
622
|
-
* name: '节点1',
|
|
623
|
-
* children: [
|
|
624
|
-
* { id: '2', name: '节点2', children: [] }
|
|
625
|
-
* ]
|
|
626
|
-
* }
|
|
627
|
-
* ]
|
|
628
|
-
*
|
|
629
|
-
* const success = Tree.insertAfter(tree, '2', { id: '3', name: '新节点' })
|
|
630
|
-
* console.log(success) // true
|
|
631
|
-
* ```
|
|
632
|
-
*/
|
|
633
|
-
static insertAfter<T = any>(tree: TreeNode<T>[], targetId: string, newNode: T, config?: TreeConfigInput): boolean;
|
|
634
|
-
/**
|
|
635
|
-
* 从树中删除指定节点
|
|
636
|
-
*
|
|
637
|
-
* @category Data Structures
|
|
638
|
-
* @param tree 树形结构数组
|
|
639
|
-
* @param targetId 要删除的节点ID
|
|
640
|
-
* @param config 树形配置选项
|
|
641
|
-
* @returns 被删除的节点,未找到时返回undefined
|
|
642
|
-
* @example
|
|
643
|
-
* ```ts
|
|
644
|
-
* const tree = [
|
|
645
|
-
* {
|
|
646
|
-
* id: '1',
|
|
647
|
-
* name: '根节点',
|
|
648
|
-
* children: [
|
|
649
|
-
* { id: '2', name: '子节点', children: [] }
|
|
650
|
-
* ]
|
|
651
|
-
* }
|
|
652
|
-
* ]
|
|
653
|
-
*
|
|
654
|
-
* const removed = Tree.remove(tree, '2')
|
|
655
|
-
* console.log(removed?.name) // '子节点'
|
|
656
|
-
* ```
|
|
657
|
-
*/
|
|
658
|
-
static remove<T = any>(tree: TreeNode<T>[], targetId: string, config?: TreeConfigInput): TreeNode<T> | undefined;
|
|
659
|
-
/**
|
|
660
|
-
* 验证树形结构的有效性
|
|
661
|
-
*
|
|
662
|
-
* @category Data Structures
|
|
663
|
-
* @param tree 树形结构(单个节点或节点数组)
|
|
664
|
-
* @param config 树形配置选项
|
|
665
|
-
* @returns 验证结果,包含是否有效和错误信息数组
|
|
666
|
-
* @example
|
|
667
|
-
* ```ts
|
|
668
|
-
* const tree = [
|
|
669
|
-
* {
|
|
670
|
-
* id: '1',
|
|
671
|
-
* name: '根节点',
|
|
672
|
-
* children: [
|
|
673
|
-
* { id: '2', name: '子节点', children: [] }
|
|
674
|
-
* ]
|
|
675
|
-
* }
|
|
676
|
-
* ]
|
|
677
|
-
*
|
|
678
|
-
* const result = Tree.validate(tree)
|
|
679
|
-
* console.log(result.isValid) // true
|
|
680
|
-
* console.log(result.errors) // []
|
|
681
|
-
* ```
|
|
682
|
-
*/
|
|
683
|
-
static validate<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): {
|
|
684
|
-
isValid: boolean;
|
|
685
|
-
errors: string[];
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
/**
|
|
690
|
-
* 数组去重,返回去除重复元素后的新数组
|
|
691
|
-
*
|
|
692
|
-
* @category Array
|
|
693
|
-
* @param arr 待去重的数组
|
|
694
|
-
* @returns 去重后的新数组
|
|
695
|
-
* @example
|
|
696
|
-
* ```ts
|
|
697
|
-
* const numbers = [1, 2, 2, 3, 3, 4]
|
|
698
|
-
* const uniqueNumbers = unique(numbers)
|
|
699
|
-
* console.log(uniqueNumbers) // [1, 2, 3, 4]
|
|
700
|
-
*
|
|
701
|
-
* const strings = ['a', 'b', 'a', 'c']
|
|
702
|
-
* const uniqueStrings = unique(strings)
|
|
703
|
-
* console.log(uniqueStrings) // ['a', 'b', 'c']
|
|
704
|
-
* ```
|
|
705
|
-
*/
|
|
706
|
-
declare function unique<T>(arr: T[]): T[];
|
|
707
|
-
/**
|
|
708
|
-
* 将数组分割成指定大小的块
|
|
709
|
-
*
|
|
710
|
-
* @category Array
|
|
711
|
-
* @param arr 待分割的数组
|
|
712
|
-
* @param size 每个块的大小
|
|
713
|
-
* @returns 分割后的二维数组
|
|
714
|
-
* @example
|
|
715
|
-
* ```ts
|
|
716
|
-
* const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
717
|
-
* const chunks = chunk(numbers, 3)
|
|
718
|
-
* console.log(chunks) // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
|
719
|
-
*
|
|
720
|
-
* const names = ['Alice', 'Bob', 'Charlie', 'David', 'Eve']
|
|
721
|
-
* const pairs = chunk(names, 2)
|
|
722
|
-
* console.log(pairs) // [['Alice', 'Bob'], ['Charlie', 'David'], ['Eve']]
|
|
723
|
-
* ```
|
|
724
|
-
*/
|
|
725
|
-
declare function chunk<T>(arr: T[], size: number): T[][];
|
|
726
|
-
/**
|
|
727
|
-
* 数组扁平化,将嵌套数组展平到指定深度
|
|
728
|
-
*
|
|
729
|
-
* @category Array
|
|
730
|
-
* @param arr 待扁平化的数组
|
|
731
|
-
* @param depth 扁平化深度,默认为1
|
|
732
|
-
* @returns 扁平化后的数组
|
|
733
|
-
* @example
|
|
734
|
-
* ```ts
|
|
735
|
-
* const nested = [1, [2, 3], [4, [5, 6]]]
|
|
736
|
-
* const flat1 = flatten(nested)
|
|
737
|
-
* console.log(flat1) // [1, 2, 3, 4, [5, 6]]
|
|
738
|
-
*
|
|
739
|
-
* const flat2 = flatten(nested, 2)
|
|
740
|
-
* console.log(flat2) // [1, 2, 3, 4, 5, 6]
|
|
741
|
-
* ```
|
|
742
|
-
*/
|
|
743
|
-
declare function flatten<T>(arr: T[], depth?: number): any[];
|
|
744
|
-
|
|
745
|
-
/**
|
|
746
|
-
* 防抖函数,在指定时间内多次触发只执行最后一次
|
|
747
|
-
*
|
|
748
|
-
* @category Async
|
|
749
|
-
* @param func 需要防抖的函数
|
|
750
|
-
* @param wait 防抖延迟时间(毫秒)
|
|
751
|
-
* @returns 防抖处理后的函数
|
|
752
|
-
* @example
|
|
753
|
-
* ```ts
|
|
754
|
-
* const debouncedSearch = debounce((query: string) => {
|
|
755
|
-
* console.log('搜索:', query)
|
|
756
|
-
* }, 300)
|
|
757
|
-
*
|
|
758
|
-
* // 连续调用,只有最后一次会执行
|
|
759
|
-
* debouncedSearch('a')
|
|
760
|
-
* debouncedSearch('ab')
|
|
761
|
-
* debouncedSearch('abc') // 只有这次会在300ms后执行
|
|
762
|
-
* ```
|
|
763
|
-
*/
|
|
764
|
-
declare function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void;
|
|
765
|
-
|
|
766
|
-
/**
|
|
767
|
-
* 延迟执行函数,返回一个在指定时间后resolve的Promise
|
|
768
|
-
*
|
|
769
|
-
* @category Async
|
|
770
|
-
* @param ms 延迟时间(毫秒)
|
|
771
|
-
* @returns 延迟Promise
|
|
772
|
-
* @example
|
|
773
|
-
* ```ts
|
|
774
|
-
* // 延迟1秒后继续执行
|
|
775
|
-
* await sleep(1000)
|
|
776
|
-
* console.log('1秒后执行')
|
|
777
|
-
*
|
|
778
|
-
* // 在异步函数中使用
|
|
779
|
-
* async function delayedOperation() {
|
|
780
|
-
* console.log('开始')
|
|
781
|
-
* await sleep(500)
|
|
782
|
-
* console.log('500ms后执行')
|
|
783
|
-
* }
|
|
784
|
-
* ```
|
|
785
|
-
*/
|
|
786
|
-
declare function sleep(ms: number): Promise<void>;
|
|
787
|
-
/**
|
|
788
|
-
* 可取消的延迟函数,返回Promise和取消函数
|
|
789
|
-
*
|
|
790
|
-
* @category Async
|
|
791
|
-
* @param ms 延迟时间(毫秒)
|
|
792
|
-
* @returns 包含Promise和取消函数的对象
|
|
793
|
-
* @example
|
|
794
|
-
* ```ts
|
|
795
|
-
* const { promise, cancel } = sleepWithCancel(5000)
|
|
796
|
-
*
|
|
797
|
-
* // 在另一个地方取消延迟
|
|
798
|
-
* setTimeout(() => {
|
|
799
|
-
* cancel() // 取消延迟
|
|
800
|
-
* }, 2000)
|
|
801
|
-
*
|
|
802
|
-
* try {
|
|
803
|
-
* await promise
|
|
804
|
-
* console.log('5秒后执行')
|
|
805
|
-
* } catch (error) {
|
|
806
|
-
* console.log('延迟被取消')
|
|
807
|
-
* }
|
|
808
|
-
* ```
|
|
809
|
-
*/
|
|
810
|
-
declare function sleepWithCancel(ms: number): {
|
|
811
|
-
promise: Promise<void>;
|
|
812
|
-
cancel: () => void;
|
|
469
|
+
/**
|
|
470
|
+
* 数组去重,返回去除重复元素后的新数组
|
|
471
|
+
*
|
|
472
|
+
* @category Array
|
|
473
|
+
* @param arr 待去重的数组
|
|
474
|
+
* @returns 去重后的新数组
|
|
475
|
+
* @example
|
|
476
|
+
* ```ts
|
|
477
|
+
* const numbers = [1, 2, 2, 3, 3, 4]
|
|
478
|
+
* const uniqueNumbers = unique(numbers)
|
|
479
|
+
* console.log(uniqueNumbers) // [1, 2, 3, 4]
|
|
480
|
+
*
|
|
481
|
+
* const strings = ['a', 'b', 'a', 'c']
|
|
482
|
+
* const uniqueStrings = unique(strings)
|
|
483
|
+
* console.log(uniqueStrings) // ['a', 'b', 'c']
|
|
484
|
+
* ```
|
|
485
|
+
*/
|
|
486
|
+
declare function unique<T>(arr: T[]): T[];
|
|
487
|
+
/**
|
|
488
|
+
* 将数组分割成指定大小的块
|
|
489
|
+
*
|
|
490
|
+
* @category Array
|
|
491
|
+
* @param arr 待分割的数组
|
|
492
|
+
* @param size 每个块的大小
|
|
493
|
+
* @returns 分割后的二维数组
|
|
494
|
+
* @example
|
|
495
|
+
* ```ts
|
|
496
|
+
* const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
497
|
+
* const chunks = chunk(numbers, 3)
|
|
498
|
+
* console.log(chunks) // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
|
499
|
+
*
|
|
500
|
+
* const names = ['Alice', 'Bob', 'Charlie', 'David', 'Eve']
|
|
501
|
+
* const pairs = chunk(names, 2)
|
|
502
|
+
* console.log(pairs) // [['Alice', 'Bob'], ['Charlie', 'David'], ['Eve']]
|
|
503
|
+
* ```
|
|
504
|
+
*/
|
|
505
|
+
declare function chunk<T>(arr: T[], size: number): T[][];
|
|
506
|
+
/**
|
|
507
|
+
* 数组扁平化,将嵌套数组展平到指定深度
|
|
508
|
+
*
|
|
509
|
+
* @category Array
|
|
510
|
+
* @param arr 待扁平化的数组
|
|
511
|
+
* @param depth 扁平化深度,默认为1
|
|
512
|
+
* @returns 扁平化后的数组
|
|
513
|
+
* @example
|
|
514
|
+
* ```ts
|
|
515
|
+
* const nested = [1, [2, 3], [4, [5, 6]]]
|
|
516
|
+
* const flat1 = flatten(nested)
|
|
517
|
+
* console.log(flat1) // [1, 2, 3, 4, [5, 6]]
|
|
518
|
+
*
|
|
519
|
+
* const flat2 = flatten(nested, 2)
|
|
520
|
+
* console.log(flat2) // [1, 2, 3, 4, 5, 6]
|
|
521
|
+
* ```
|
|
522
|
+
*/
|
|
523
|
+
declare function flatten<T>(arr: T[], depth?: number): any[];
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* 防抖函数,在指定时间内多次触发只执行最后一次
|
|
527
|
+
*
|
|
528
|
+
* @category Async
|
|
529
|
+
* @param func 需要防抖的函数
|
|
530
|
+
* @param wait 防抖延迟时间(毫秒)
|
|
531
|
+
* @returns 防抖处理后的函数
|
|
532
|
+
* @example
|
|
533
|
+
* ```ts
|
|
534
|
+
* const debouncedSearch = debounce((query: string) => {
|
|
535
|
+
* console.log('搜索:', query)
|
|
536
|
+
* }, 300)
|
|
537
|
+
*
|
|
538
|
+
* // 连续调用,只有最后一次会执行
|
|
539
|
+
* debouncedSearch('a')
|
|
540
|
+
* debouncedSearch('ab')
|
|
541
|
+
* debouncedSearch('abc') // 只有这次会在300ms后执行
|
|
542
|
+
* ```
|
|
543
|
+
*/
|
|
544
|
+
declare function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void;
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* 延迟执行函数,返回一个在指定时间后resolve的Promise
|
|
548
|
+
*
|
|
549
|
+
* @category Async
|
|
550
|
+
* @param ms 延迟时间(毫秒)
|
|
551
|
+
* @returns 延迟Promise
|
|
552
|
+
* @example
|
|
553
|
+
* ```ts
|
|
554
|
+
* // 延迟1秒后继续执行
|
|
555
|
+
* await sleep(1000)
|
|
556
|
+
* console.log('1秒后执行')
|
|
557
|
+
*
|
|
558
|
+
* // 在异步函数中使用
|
|
559
|
+
* async function delayedOperation() {
|
|
560
|
+
* console.log('开始')
|
|
561
|
+
* await sleep(500)
|
|
562
|
+
* console.log('500ms后执行')
|
|
563
|
+
* }
|
|
564
|
+
* ```
|
|
565
|
+
*/
|
|
566
|
+
declare function sleep(ms: number): Promise<void>;
|
|
567
|
+
/**
|
|
568
|
+
* 可取消的延迟函数,返回Promise和取消函数
|
|
569
|
+
*
|
|
570
|
+
* @category Async
|
|
571
|
+
* @param ms 延迟时间(毫秒)
|
|
572
|
+
* @returns 包含Promise和取消函数的对象
|
|
573
|
+
* @example
|
|
574
|
+
* ```ts
|
|
575
|
+
* const { promise, cancel } = sleepWithCancel(5000)
|
|
576
|
+
*
|
|
577
|
+
* // 在另一个地方取消延迟
|
|
578
|
+
* setTimeout(() => {
|
|
579
|
+
* cancel() // 取消延迟
|
|
580
|
+
* }, 2000)
|
|
581
|
+
*
|
|
582
|
+
* try {
|
|
583
|
+
* await promise
|
|
584
|
+
* console.log('5秒后执行')
|
|
585
|
+
* } catch (error) {
|
|
586
|
+
* console.log('延迟被取消')
|
|
587
|
+
* }
|
|
588
|
+
* ```
|
|
589
|
+
*/
|
|
590
|
+
declare function sleepWithCancel(ms: number): {
|
|
591
|
+
promise: Promise<void>;
|
|
592
|
+
cancel: () => void;
|
|
813
593
|
};
|
|
814
594
|
|
|
815
595
|
/**
|
|
@@ -994,34 +774,34 @@ declare function replaceCurrentColor(path: string, color?: string): Promise<stri
|
|
|
994
774
|
declare function convertToKebabCase<T extends AnyObject>(obj: T, deep?: boolean): T;
|
|
995
775
|
|
|
996
776
|
/**
|
|
997
|
-
*
|
|
777
|
+
* 深拷贝任意 JavaScript 值。
|
|
778
|
+
*
|
|
779
|
+
* - 优先使用原生 `structuredClone`(若可用),覆盖 `Map`/`Set`/`TypedArray`/`ArrayBuffer` 等内建类型。
|
|
780
|
+
* - 对不支持 `structuredClone` 的环境,使用回退实现:
|
|
781
|
+
* - 支持循环引用(`WeakMap` 记忆化)。
|
|
782
|
+
* - 保留原型与属性描述符(含 getter/setter),复制 symbol 键。
|
|
783
|
+
* - 内建类型专项处理:`Date`/`RegExp`/`Map`/`Set`/`ArrayBuffer`/`TypedArray`/`URL`/`Error`。
|
|
998
784
|
*
|
|
999
785
|
* @category Object
|
|
1000
|
-
* @
|
|
1001
|
-
* @
|
|
786
|
+
* @typeParam T 拷贝值的类型
|
|
787
|
+
* @param obj 要被深拷贝的值
|
|
788
|
+
* @param cache 内部使用的 `WeakMap`(循环引用记忆化),一般不需要传入
|
|
789
|
+
* @returns 新的深拷贝值,与输入值结构等价、引用独立
|
|
790
|
+
*
|
|
1002
791
|
* @example
|
|
1003
792
|
* ```ts
|
|
1004
|
-
* const
|
|
1005
|
-
*
|
|
1006
|
-
*
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1010
|
-
* },
|
|
1011
|
-
* hobbies: ['reading', 'coding']
|
|
1012
|
-
* }
|
|
1013
|
-
*
|
|
1014
|
-
* const cloned = deepClone(original)
|
|
1015
|
-
* cloned.address.city = 'Los Angeles'
|
|
1016
|
-
* cloned.hobbies.push('gaming')
|
|
1017
|
-
*
|
|
1018
|
-
* console.log(original.address.city) // 'New York' (未改变)
|
|
1019
|
-
* console.log(original.hobbies.length) // 2 (未改变)
|
|
1020
|
-
* console.log(cloned.address.city) // 'Los Angeles'
|
|
1021
|
-
* console.log(cloned.hobbies.length) // 3
|
|
793
|
+
* const source = { a: 1, d: new Date(), m: new Map([[1, { x: 2 }]]) }
|
|
794
|
+
* const cloned = deepClone(source)
|
|
795
|
+
* cloned !== source // true
|
|
796
|
+
* cloned.d !== source.d // true
|
|
797
|
+
* cloned.m !== source.m // true
|
|
798
|
+
* cloned.m.get(1) !== source.m.get(1) // true
|
|
1022
799
|
* ```
|
|
800
|
+
*
|
|
801
|
+
* @remarks
|
|
802
|
+
* 若对象包含不可克隆资源(如带有原生句柄的自定义对象),请在外层进行自定义序列化逻辑或为该类型添加专用分支。
|
|
1023
803
|
*/
|
|
1024
|
-
declare function deepClone<T>(obj: T): T;
|
|
804
|
+
declare function deepClone<T>(obj: T, cache?: WeakMap<object, any>): T;
|
|
1025
805
|
|
|
1026
806
|
/**
|
|
1027
807
|
* 从对象中排除指定的键,返回新对象
|
|
@@ -1039,42 +819,157 @@ declare function deepClone<T>(obj: T): T;
|
|
|
1039
819
|
* email: 'john@example.com'
|
|
1040
820
|
* }
|
|
1041
821
|
*
|
|
1042
|
-
* const publicUser = omit(user, ['password'])
|
|
1043
|
-
* console.log(publicUser) // { id: 1, name: 'John', email: 'john@example.com' }
|
|
822
|
+
* const publicUser = omit(user, ['password'])
|
|
823
|
+
* console.log(publicUser) // { id: 1, name: 'John', email: 'john@example.com' }
|
|
824
|
+
*
|
|
825
|
+
* const basicInfo = omit(user, ['password', 'email'])
|
|
826
|
+
* console.log(basicInfo) // { id: 1, name: 'John' }
|
|
827
|
+
* ```
|
|
828
|
+
*/
|
|
829
|
+
declare function omit<T extends AnyObject, K extends keyof T>(obj: T, keys: K[]): OmitByKey<T, K>;
|
|
830
|
+
/**
|
|
831
|
+
* 从对象中排除值为undefined的键
|
|
832
|
+
*
|
|
833
|
+
* @category Object
|
|
834
|
+
* @param obj 源对象
|
|
835
|
+
* @returns 排除undefined值后的新对象
|
|
836
|
+
* @example
|
|
837
|
+
* ```ts
|
|
838
|
+
* const data = {
|
|
839
|
+
* name: 'John',
|
|
840
|
+
* age: undefined,
|
|
841
|
+
* city: 'New York',
|
|
842
|
+
* country: undefined
|
|
843
|
+
* }
|
|
844
|
+
*
|
|
845
|
+
* const cleaned = omitUndefined(data)
|
|
846
|
+
* console.log(cleaned) // { name: 'John', city: 'New York' }
|
|
847
|
+
*
|
|
848
|
+
* // 用于API请求前清理数据
|
|
849
|
+
* const requestData = omitUndefined({
|
|
850
|
+
* title: 'Post Title',
|
|
851
|
+
* content: 'Post content',
|
|
852
|
+
* tags: undefined,
|
|
853
|
+
* published: true
|
|
854
|
+
* })
|
|
855
|
+
* ```
|
|
856
|
+
*/
|
|
857
|
+
declare function omitUndefined<T extends AnyObject>(obj: T): Partial<T>;
|
|
858
|
+
|
|
859
|
+
type PathSegment = string | number;
|
|
860
|
+
type PathSegments = PathSegment[];
|
|
861
|
+
type PathInput = string | PathSegments;
|
|
862
|
+
/**
|
|
863
|
+
* 检查值是否为有效的容器类型(对象或数组)
|
|
864
|
+
*
|
|
865
|
+
* - isObject: 仅检查纯对象,排除数组
|
|
866
|
+
* - isValidContainer: 检查所有可作为容器的类型(对象 + 数组)
|
|
867
|
+
*
|
|
868
|
+
* 支持 Vue 3 的 Proxy 对象和 Proxy 数组。
|
|
869
|
+
*
|
|
870
|
+
* @category Validator
|
|
871
|
+
* @param value - 待检查的值
|
|
872
|
+
* @returns 是否为有效容器(对象或数组)
|
|
873
|
+
* @example
|
|
874
|
+
* ```ts
|
|
875
|
+
* isValidContainer({}) // true
|
|
876
|
+
* isValidContainer([]) // true
|
|
877
|
+
* isValidContainer(new Proxy({}, {})) // true
|
|
878
|
+
* isValidContainer(null) // false
|
|
879
|
+
* isValidContainer('string') // false
|
|
880
|
+
* isValidContainer(123) // false
|
|
881
|
+
* ```
|
|
882
|
+
*/
|
|
883
|
+
declare function isValidContainer(value: any): boolean;
|
|
884
|
+
/**
|
|
885
|
+
* 将路径字符串解析为片段数组。
|
|
886
|
+
*
|
|
887
|
+
* - 支持点语法与方括号语法混用
|
|
888
|
+
* - 引号键支持单/双引号与反斜杠转义
|
|
889
|
+
* - 方括号内未引号的非负整数字面量解析为 number 段
|
|
890
|
+
* - 点语法中的纯数字段保持字符串(不转为索引)
|
|
891
|
+
*
|
|
892
|
+
* @category Object
|
|
893
|
+
* @param path 路径字符串或片段数组
|
|
894
|
+
* @returns 解析后的片段数组
|
|
895
|
+
* @example
|
|
896
|
+
* ```ts
|
|
897
|
+
* toPath('a.b[0].c') // ['a', 'b', 0, 'c']
|
|
898
|
+
* toPath("a['x.y']") // ['a', 'x.y']
|
|
899
|
+
* ```
|
|
900
|
+
*/
|
|
901
|
+
declare function toPath(path: PathInput): PathSegments;
|
|
902
|
+
/**
|
|
903
|
+
* 读取对象指定路径的值。
|
|
904
|
+
*
|
|
905
|
+
* - 若取值结果为 undefined,则返回 defaultValue
|
|
906
|
+
* - 若取值结果为 null,则直接返回 null(不触发默认值)
|
|
907
|
+
* - 传入空路径时返回 object 本身
|
|
1044
908
|
*
|
|
1045
|
-
*
|
|
1046
|
-
*
|
|
909
|
+
* @category Object
|
|
910
|
+
* @param object 源对象
|
|
911
|
+
* @param path 路径字符串或片段数组
|
|
912
|
+
* @param defaultValue 结果为 undefined 时返回的默认值
|
|
913
|
+
* @returns 读取到的值或默认值
|
|
914
|
+
* @example
|
|
915
|
+
* ```ts
|
|
916
|
+
* const obj = { a: { b: { c: 1, d: undefined }, e: null }, arr: [{ x: 9 }] }
|
|
917
|
+
* getPath(obj, 'a.b.c') // 1
|
|
918
|
+
* getPath(obj, 'a.b.d', 42) // 42(d 为 undefined,使用默认值)
|
|
919
|
+
* getPath(obj, 'a.e', 100) // null(null 不触发默认值)
|
|
920
|
+
* getPath(obj, 'arr[0].x') // 9
|
|
921
|
+
* getPath(obj, '') // 返回 obj 本身
|
|
1047
922
|
* ```
|
|
1048
923
|
*/
|
|
1049
|
-
declare function
|
|
924
|
+
declare function getPath<T, D = undefined>(object: T, path: PathInput, defaultValue?: D): unknown | D;
|
|
1050
925
|
/**
|
|
1051
|
-
*
|
|
926
|
+
* 在对象指定路径写入值。缺失路径会被自动创建:
|
|
927
|
+
* - 下一段为 number(索引)时创建数组
|
|
928
|
+
* - 下一段为 string(属性)时创建对象
|
|
929
|
+
*
|
|
930
|
+
* 若中途遇到非容器类型(如字符串/数值/布尔),会被替换为正确的容器以继续写入。
|
|
1052
931
|
*
|
|
1053
932
|
* @category Object
|
|
1054
|
-
* @param
|
|
1055
|
-
* @
|
|
933
|
+
* @param object 目标对象(原地修改并返回同一引用)
|
|
934
|
+
* @param path 路径字符串或片段数组
|
|
935
|
+
* @param value 要写入的值
|
|
936
|
+
* @returns 原对象(已修改)
|
|
1056
937
|
* @example
|
|
1057
938
|
* ```ts
|
|
1058
|
-
* const
|
|
1059
|
-
*
|
|
1060
|
-
*
|
|
1061
|
-
*
|
|
1062
|
-
*
|
|
1063
|
-
*
|
|
939
|
+
* const obj: any = {}
|
|
940
|
+
* setPath(obj, 'a.b[0].c', 7)
|
|
941
|
+
* // obj => { a: { b: [{ c: 7 }] } }
|
|
942
|
+
*
|
|
943
|
+
* setPath(obj, 'a.b[2].d', 8)
|
|
944
|
+
* // 数组自动扩容到长度 3
|
|
945
|
+
* // obj.a.b[2] => { d: 8 }
|
|
946
|
+
*
|
|
947
|
+
* setPath(obj, 'a.0.b', 1) // 点语法数字键保持为字符串键
|
|
948
|
+
* // obj => { a: { 0: { b: 1 } } }
|
|
949
|
+
* setPath(obj, 'a[0].b', 2) // 索引用方括号
|
|
950
|
+
* // obj.a[0].b => 2
|
|
951
|
+
* ```
|
|
952
|
+
*/
|
|
953
|
+
declare function setPath<T extends Record<string, any>>(object: T, path: PathInput, value: unknown): T;
|
|
954
|
+
/**
|
|
955
|
+
* 将片段数组序列化为路径字符串。
|
|
1064
956
|
*
|
|
1065
|
-
*
|
|
1066
|
-
*
|
|
957
|
+
* 规则:
|
|
958
|
+
* - 合法标识符段使用点拼接(a.b.c)
|
|
959
|
+
* - 数字段转为索引([0])
|
|
960
|
+
* - 其它需要转义的键使用方括号引号(['x.y']),并转义 \\ 与 '\''
|
|
1067
961
|
*
|
|
1068
|
-
*
|
|
1069
|
-
*
|
|
1070
|
-
*
|
|
1071
|
-
*
|
|
1072
|
-
*
|
|
1073
|
-
*
|
|
1074
|
-
*
|
|
962
|
+
* @category Object
|
|
963
|
+
* @param segments 路径片段数组
|
|
964
|
+
* @returns 路径字符串
|
|
965
|
+
* @example
|
|
966
|
+
* ```ts
|
|
967
|
+
* const p = joinPath(['a', 'x.y', 0, 'space key'])
|
|
968
|
+
* // p: "a['x.y'][0]['space key']"
|
|
969
|
+
* // 与解析往返:toPath(p) => ['a', 'x.y', 0, 'space key']
|
|
1075
970
|
* ```
|
|
1076
971
|
*/
|
|
1077
|
-
declare function
|
|
972
|
+
declare function joinPath(segments: (string | number)[]): string;
|
|
1078
973
|
|
|
1079
974
|
/**
|
|
1080
975
|
* 从对象中选择指定的键,返回新对象
|
|
@@ -1159,50 +1054,677 @@ declare function separateMany<T extends AnyObject, M extends Record<string, read
|
|
|
1159
1054
|
};
|
|
1160
1055
|
|
|
1161
1056
|
/**
|
|
1162
|
-
*
|
|
1057
|
+
* 将字符串转换为Start Case格式(每个单词首字母大写,用空格分隔)。
|
|
1058
|
+
*
|
|
1059
|
+
* @category String
|
|
1060
|
+
* @param str 要转换的字符串
|
|
1061
|
+
* @returns Start Case格式的字符串
|
|
1062
|
+
* @example
|
|
1063
|
+
* ```ts
|
|
1064
|
+
* startCase('firstName') // 'First Name'
|
|
1065
|
+
* startCase('first_name') // 'First Name'
|
|
1066
|
+
* startCase('first-name') // 'First Name'
|
|
1067
|
+
* startCase('XMLHttpRequest') // 'XML Http Request'
|
|
1068
|
+
* ```
|
|
1069
|
+
*/
|
|
1070
|
+
declare function startCase(str: string): string;
|
|
1071
|
+
/**
|
|
1072
|
+
* 将字符串转换为驼峰命名格式(第一个单词小写,后续单词首字母大写)。
|
|
1073
|
+
*
|
|
1074
|
+
* @category String
|
|
1075
|
+
* @param str 要转换的字符串
|
|
1076
|
+
* @returns 驼峰命名格式的字符串
|
|
1077
|
+
* @example
|
|
1078
|
+
* ```ts
|
|
1079
|
+
* camelCase('First Name') // 'firstName'
|
|
1080
|
+
* camelCase('first_name') // 'firstName'
|
|
1081
|
+
* camelCase('first-name') // 'firstName'
|
|
1082
|
+
* camelCase('XMLHttpRequest') // 'xmlHttpRequest'
|
|
1083
|
+
* ```
|
|
1084
|
+
*/
|
|
1085
|
+
declare function camelCase(str: string): string;
|
|
1086
|
+
/**
|
|
1087
|
+
* 将字符串转换为短横线命名格式(kebab-case)。
|
|
1088
|
+
*
|
|
1089
|
+
* @category String
|
|
1090
|
+
* @param str 要转换的字符串
|
|
1091
|
+
* @returns 短横线命名格式的字符串
|
|
1092
|
+
* @example
|
|
1093
|
+
* ```ts
|
|
1094
|
+
* kebabCase('firstName') // 'first-name'
|
|
1095
|
+
* kebabCase('First Name') // 'first-name'
|
|
1096
|
+
* kebabCase('first_name') // 'first-name'
|
|
1097
|
+
* kebabCase('XMLHttpRequest') // 'xml-http-request'
|
|
1098
|
+
* ```
|
|
1099
|
+
*/
|
|
1100
|
+
declare function kebabCase(str: string): string;
|
|
1101
|
+
/**
|
|
1102
|
+
* 将字符串转换为下划线命名格式(snake_case)。
|
|
1103
|
+
*
|
|
1104
|
+
* @category String
|
|
1105
|
+
* @param str 要转换的字符串
|
|
1106
|
+
* @returns 下划线命名格式的字符串
|
|
1107
|
+
* @example
|
|
1108
|
+
* ```ts
|
|
1109
|
+
* snakeCase('firstName') // 'first_name'
|
|
1110
|
+
* snakeCase('First Name') // 'first_name'
|
|
1111
|
+
* snakeCase('first-name') // 'first_name'
|
|
1112
|
+
* snakeCase('XMLHttpRequest') // 'xml_http_request'
|
|
1113
|
+
* ```
|
|
1114
|
+
*/
|
|
1115
|
+
declare function snakeCase(str: string): string;
|
|
1116
|
+
/**
|
|
1117
|
+
* 将字符串转换为帕斯卡命名格式(PascalCase,每个单词首字母大写)。
|
|
1118
|
+
*
|
|
1119
|
+
* @category String
|
|
1120
|
+
* @param str 要转换的字符串
|
|
1121
|
+
* @returns 帕斯卡命名格式的字符串
|
|
1122
|
+
* @example
|
|
1123
|
+
* ```ts
|
|
1124
|
+
* pascalCase('firstName') // 'FirstName'
|
|
1125
|
+
* pascalCase('first_name') // 'FirstName'
|
|
1126
|
+
* pascalCase('first-name') // 'FirstName'
|
|
1127
|
+
* pascalCase('XMLHttpRequest') // 'XmlHttpRequest'
|
|
1128
|
+
* ```
|
|
1129
|
+
*/
|
|
1130
|
+
declare function pascalCase(str: string): string;
|
|
1131
|
+
/**
|
|
1132
|
+
* 将字符串首字母大写,其余字母小写。
|
|
1163
1133
|
*
|
|
1164
1134
|
* @category String
|
|
1165
|
-
* @param str
|
|
1135
|
+
* @param str 要转换的字符串
|
|
1166
1136
|
* @returns 首字母大写的字符串
|
|
1167
1137
|
* @example
|
|
1168
1138
|
* ```ts
|
|
1169
|
-
*
|
|
1170
|
-
*
|
|
1171
|
-
*
|
|
1172
|
-
* console.log(capitalize('a')) // 'A'
|
|
1139
|
+
* capitalize('hello') // 'Hello'
|
|
1140
|
+
* capitalize('HELLO') // 'Hello'
|
|
1141
|
+
* capitalize('hello world') // 'Hello world'
|
|
1173
1142
|
* ```
|
|
1174
1143
|
*/
|
|
1175
1144
|
declare function capitalize(str: string): string;
|
|
1176
1145
|
/**
|
|
1177
|
-
*
|
|
1146
|
+
* 将字符串首字母大写,其余字母保持原样。
|
|
1147
|
+
*
|
|
1148
|
+
* @category String
|
|
1149
|
+
* @param str 要转换的字符串
|
|
1150
|
+
* @returns 首字母大写的字符串
|
|
1151
|
+
* @example
|
|
1152
|
+
* ```ts
|
|
1153
|
+
* upperFirst('hello') // 'Hello'
|
|
1154
|
+
* upperFirst('hELLO') // 'HELLO'
|
|
1155
|
+
* upperFirst('hello world') // 'Hello world'
|
|
1156
|
+
* ```
|
|
1157
|
+
*/
|
|
1158
|
+
declare function upperFirst(str: string): string;
|
|
1159
|
+
/**
|
|
1160
|
+
* 将字符串首字母小写,其余字母保持原样。
|
|
1161
|
+
*
|
|
1162
|
+
* @category String
|
|
1163
|
+
* @param str 要转换的字符串
|
|
1164
|
+
* @returns 首字母小写的字符串
|
|
1165
|
+
* @example
|
|
1166
|
+
* ```ts
|
|
1167
|
+
* lowerFirst('Hello') // 'hello'
|
|
1168
|
+
* lowerFirst('HELLO') // 'hELLO'
|
|
1169
|
+
* lowerFirst('Hello World') // 'hello World'
|
|
1170
|
+
* ```
|
|
1171
|
+
*/
|
|
1172
|
+
declare function lowerFirst(str: string): string;
|
|
1173
|
+
/**
|
|
1174
|
+
* 将字符串转换为大写格式,单词之间用空格分隔。
|
|
1175
|
+
*
|
|
1176
|
+
* @category String
|
|
1177
|
+
* @param str 要转换的字符串
|
|
1178
|
+
* @returns 大写格式的字符串
|
|
1179
|
+
* @example
|
|
1180
|
+
* ```ts
|
|
1181
|
+
* upperCase('firstName') // 'FIRST NAME'
|
|
1182
|
+
* upperCase('first_name') // 'FIRST NAME'
|
|
1183
|
+
* upperCase('first-name') // 'FIRST NAME'
|
|
1184
|
+
* upperCase('XMLHttpRequest') // 'XML HTTP REQUEST'
|
|
1185
|
+
* ```
|
|
1186
|
+
*/
|
|
1187
|
+
declare function upperCase(str: string): string;
|
|
1188
|
+
/**
|
|
1189
|
+
* 将字符串转换为小写格式,单词之间用空格分隔。
|
|
1178
1190
|
*
|
|
1179
1191
|
* @category String
|
|
1180
|
-
* @param str
|
|
1181
|
-
* @returns
|
|
1192
|
+
* @param str 要转换的字符串
|
|
1193
|
+
* @returns 小写格式的字符串
|
|
1182
1194
|
* @example
|
|
1183
1195
|
* ```ts
|
|
1184
|
-
*
|
|
1185
|
-
*
|
|
1186
|
-
*
|
|
1187
|
-
*
|
|
1196
|
+
* lowerCase('firstName') // 'first name'
|
|
1197
|
+
* lowerCase('First_Name') // 'first name'
|
|
1198
|
+
* lowerCase('FIRST-NAME') // 'first name'
|
|
1199
|
+
* lowerCase('XMLHttpRequest') // 'xml http request'
|
|
1188
1200
|
* ```
|
|
1189
1201
|
*/
|
|
1190
|
-
declare function
|
|
1202
|
+
declare function lowerCase(str: string): string;
|
|
1203
|
+
/**
|
|
1204
|
+
* 将驼峰命名转换为kebab-case
|
|
1205
|
+
* @deprecated Use `kebabCase` instead
|
|
1206
|
+
*/
|
|
1207
|
+
declare const camelToKebab: typeof kebabCase;
|
|
1191
1208
|
/**
|
|
1192
1209
|
* 将kebab-case转换为驼峰命名
|
|
1210
|
+
* @deprecated Use `camelCase` instead
|
|
1211
|
+
*/
|
|
1212
|
+
declare const kebabToCamel: typeof camelCase;
|
|
1213
|
+
|
|
1214
|
+
/**
|
|
1215
|
+
* 将字符串分解为单词数组。支持camelCase、snake_case、kebab-case等各种命名风格。
|
|
1193
1216
|
*
|
|
1194
1217
|
* @category String
|
|
1195
|
-
* @param str
|
|
1196
|
-
* @returns
|
|
1218
|
+
* @param str 要分解的字符串
|
|
1219
|
+
* @returns 单词数组
|
|
1220
|
+
* @example
|
|
1221
|
+
* ```ts
|
|
1222
|
+
* words('helloWorld') // ['hello', 'World']
|
|
1223
|
+
* words('hello_world') // ['hello', 'world']
|
|
1224
|
+
* words('hello-world') // ['hello', 'world']
|
|
1225
|
+
* words('XMLHttpRequest') // ['XML', 'Http', 'Request']
|
|
1226
|
+
* ```
|
|
1227
|
+
*/
|
|
1228
|
+
declare function words(str: string): string[];
|
|
1229
|
+
|
|
1230
|
+
/**
|
|
1231
|
+
* 树节点类型定义
|
|
1232
|
+
*
|
|
1233
|
+
* @template T 节点数据类型
|
|
1234
|
+
*/
|
|
1235
|
+
type TreeNode<T = any> = T & {
|
|
1236
|
+
children?: TreeNode<T>[];
|
|
1237
|
+
[key: string]: any;
|
|
1238
|
+
};
|
|
1239
|
+
declare const TreeConfigSchema: z.ZodObject<{
|
|
1240
|
+
id: z.ZodDefault<z.ZodString>;
|
|
1241
|
+
pid: z.ZodDefault<z.ZodString>;
|
|
1242
|
+
children: z.ZodDefault<z.ZodString>;
|
|
1243
|
+
}, z.core.$strip>;
|
|
1244
|
+
/**
|
|
1245
|
+
* 树形配置输入类型
|
|
1246
|
+
*/
|
|
1247
|
+
type TreeConfigInput = z.input<typeof TreeConfigSchema>;
|
|
1248
|
+
declare const _TreeStatsSchema: z.ZodObject<{
|
|
1249
|
+
total: z.ZodNumber;
|
|
1250
|
+
leaves: z.ZodNumber;
|
|
1251
|
+
depth: z.ZodNumber;
|
|
1252
|
+
branches: z.ZodNumber;
|
|
1253
|
+
}, z.core.$strip>;
|
|
1254
|
+
/**
|
|
1255
|
+
* 树统计信息类型
|
|
1256
|
+
*/
|
|
1257
|
+
type TreeStats = z.infer<typeof _TreeStatsSchema>;
|
|
1258
|
+
/**
|
|
1259
|
+
* 树节点谓词函数类型
|
|
1260
|
+
*
|
|
1261
|
+
* @template T 节点数据类型
|
|
1262
|
+
* @param params 包含节点信息的对象参数
|
|
1263
|
+
* @param params.node 当前节点
|
|
1264
|
+
* @param params.depth 节点深度(从0开始)
|
|
1265
|
+
* @param params.path 从根节点到当前节点的路径数组
|
|
1266
|
+
* @param params.index 节点在同级节点中的索引
|
|
1267
|
+
* @returns 是否满足条件
|
|
1268
|
+
*/
|
|
1269
|
+
type TreePredicate<T = any> = (params: {
|
|
1270
|
+
node: TreeNode<T>;
|
|
1271
|
+
depth: number;
|
|
1272
|
+
path: readonly TreeNode<T>[];
|
|
1273
|
+
index: number;
|
|
1274
|
+
}) => boolean;
|
|
1275
|
+
/**
|
|
1276
|
+
* 树节点转换函数类型
|
|
1277
|
+
*
|
|
1278
|
+
* @template T 源节点数据类型
|
|
1279
|
+
* @template R 目标节点数据类型
|
|
1280
|
+
* @param params 包含节点信息的对象参数
|
|
1281
|
+
* @param params.node 当前节点
|
|
1282
|
+
* @param params.depth 节点深度(从0开始)
|
|
1283
|
+
* @param params.path 从根节点到当前节点的路径数组
|
|
1284
|
+
* @param params.index 节点在同级节点中的索引
|
|
1285
|
+
* @returns 转换后的节点数据
|
|
1286
|
+
*/
|
|
1287
|
+
type TreeTransformer<T = any, R = any> = (params: {
|
|
1288
|
+
node: TreeNode<T>;
|
|
1289
|
+
depth: number;
|
|
1290
|
+
path: readonly TreeNode<T>[];
|
|
1291
|
+
index: number;
|
|
1292
|
+
}) => R;
|
|
1293
|
+
/**
|
|
1294
|
+
* 树节点访问函数类型
|
|
1295
|
+
*
|
|
1296
|
+
* @template T 节点数据类型
|
|
1297
|
+
* @param params 包含节点信息的对象参数
|
|
1298
|
+
* @param params.node 当前节点
|
|
1299
|
+
* @param params.depth 节点深度(从0开始)
|
|
1300
|
+
* @param params.path 从根节点到当前节点的路径数组
|
|
1301
|
+
* @param params.index 节点在同级节点中的索引
|
|
1302
|
+
* @returns 返回false可以终止遍历或跳过子节点
|
|
1303
|
+
*/
|
|
1304
|
+
type TreeVisitor<T = any> = (params: {
|
|
1305
|
+
node: TreeNode<T>;
|
|
1306
|
+
depth: number;
|
|
1307
|
+
path: readonly TreeNode<T>[];
|
|
1308
|
+
index: number;
|
|
1309
|
+
}) => void | boolean;
|
|
1310
|
+
/**
|
|
1311
|
+
* 树形数据结构操作工具类
|
|
1312
|
+
*
|
|
1313
|
+
* 提供了一系列操作树形数据的静态方法,包括:
|
|
1314
|
+
* - 查找:find, findAll, findById
|
|
1315
|
+
* - 转换:fromList, toList, transform
|
|
1316
|
+
* - 过滤:filter
|
|
1317
|
+
* - 遍历:forEach
|
|
1318
|
+
* - 统计:estimateSize, getStats
|
|
1319
|
+
* - 修改:insertBefore, insertAfter, remove
|
|
1320
|
+
* - 验证:validate
|
|
1321
|
+
*
|
|
1322
|
+
* 所有使用谓词函数或访问函数的方法都采用对象解构参数格式:
|
|
1323
|
+
* `({ node, depth, path, index }) => boolean`
|
|
1324
|
+
*
|
|
1197
1325
|
* @example
|
|
1198
1326
|
* ```ts
|
|
1199
|
-
*
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1202
|
-
*
|
|
1327
|
+
* const tree = [
|
|
1328
|
+
* {
|
|
1329
|
+
* id: '1',
|
|
1330
|
+
* name: '根节点',
|
|
1331
|
+
* children: [
|
|
1332
|
+
* { id: '2', name: '子节点1', children: [] },
|
|
1333
|
+
* { id: '3', name: '子节点2', children: [] }
|
|
1334
|
+
* ]
|
|
1335
|
+
* }
|
|
1336
|
+
* ]
|
|
1337
|
+
*
|
|
1338
|
+
* // 查找节点
|
|
1339
|
+
* const node = Tree.find(tree, ({ node }) => node.name === '子节点1')
|
|
1340
|
+
*
|
|
1341
|
+
* // 遍历所有节点
|
|
1342
|
+
* Tree.forEach(tree, ({ node, depth }) => {
|
|
1343
|
+
* console.log(`${' '.repeat(depth)}${node.name}`)
|
|
1344
|
+
* })
|
|
1345
|
+
*
|
|
1346
|
+
* // 转换节点结构
|
|
1347
|
+
* const transformed = Tree.transform(tree, ({ node, depth }) => ({
|
|
1348
|
+
* key: node.id,
|
|
1349
|
+
* title: node.name,
|
|
1350
|
+
* level: depth
|
|
1351
|
+
* }))
|
|
1203
1352
|
* ```
|
|
1204
1353
|
*/
|
|
1205
|
-
declare
|
|
1354
|
+
declare class Tree {
|
|
1355
|
+
private static dfsGenerator;
|
|
1356
|
+
private static bfsGenerator;
|
|
1357
|
+
private static selectStrategy;
|
|
1358
|
+
/**
|
|
1359
|
+
* 从扁平数组创建树形结构
|
|
1360
|
+
*
|
|
1361
|
+
* @category Data Structures
|
|
1362
|
+
* @param list 扁平数组数据
|
|
1363
|
+
* @param config 树形配置选项
|
|
1364
|
+
* @returns 树形结构数组
|
|
1365
|
+
* @example
|
|
1366
|
+
* ```ts
|
|
1367
|
+
* const flatData = [
|
|
1368
|
+
* { id: '1', name: '部门1', parentId: null },
|
|
1369
|
+
* { id: '2', name: '部门1-1', parentId: '1' },
|
|
1370
|
+
* { id: '3', name: '部门1-2', parentId: '1' },
|
|
1371
|
+
* { id: '4', name: '部门1-1-1', parentId: '2' }
|
|
1372
|
+
* ]
|
|
1373
|
+
*
|
|
1374
|
+
* const tree = Tree.fromList(flatData, {
|
|
1375
|
+
* id: 'id',
|
|
1376
|
+
* pid: 'parentId',
|
|
1377
|
+
* children: 'children'
|
|
1378
|
+
* })
|
|
1379
|
+
*
|
|
1380
|
+
* console.log(tree) // 转换为树形结构
|
|
1381
|
+
* ```
|
|
1382
|
+
*/
|
|
1383
|
+
static fromList<T = any>(list: T[], config?: TreeConfigInput): TreeNode<T>[];
|
|
1384
|
+
/**
|
|
1385
|
+
* 将树形结构转换为扁平数组
|
|
1386
|
+
*
|
|
1387
|
+
* @category Data Structures
|
|
1388
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
1389
|
+
* @param config 树形配置选项
|
|
1390
|
+
* @returns 扁平数组
|
|
1391
|
+
* @example
|
|
1392
|
+
* ```ts
|
|
1393
|
+
* const tree = [
|
|
1394
|
+
* {
|
|
1395
|
+
* id: '1',
|
|
1396
|
+
* name: '根节点',
|
|
1397
|
+
* children: [
|
|
1398
|
+
* { id: '2', name: '子节点1', children: [] },
|
|
1399
|
+
* { id: '3', name: '子节点2', children: [] }
|
|
1400
|
+
* ]
|
|
1401
|
+
* }
|
|
1402
|
+
* ]
|
|
1403
|
+
*
|
|
1404
|
+
* const flatList = Tree.toList(tree)
|
|
1405
|
+
* console.log(flatList) // [{ id: '1', name: '根节点' }, { id: '2', name: '子节点1' }, ...]
|
|
1406
|
+
* ```
|
|
1407
|
+
*/
|
|
1408
|
+
static toList<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): T[];
|
|
1409
|
+
/**
|
|
1410
|
+
* 估算树形结构的节点数量
|
|
1411
|
+
*
|
|
1412
|
+
* @category Data Structures
|
|
1413
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
1414
|
+
* @param config 树形配置选项
|
|
1415
|
+
* @returns 节点总数量
|
|
1416
|
+
* @example
|
|
1417
|
+
* ```ts
|
|
1418
|
+
* const tree = [
|
|
1419
|
+
* {
|
|
1420
|
+
* id: '1',
|
|
1421
|
+
* name: '根节点',
|
|
1422
|
+
* children: [
|
|
1423
|
+
* { id: '2', name: '子节点1', children: [] },
|
|
1424
|
+
* { id: '3', name: '子节点2', children: [] }
|
|
1425
|
+
* ]
|
|
1426
|
+
* }
|
|
1427
|
+
* ]
|
|
1428
|
+
*
|
|
1429
|
+
* const size = Tree.estimateSize(tree)
|
|
1430
|
+
* console.log(size) // 3
|
|
1431
|
+
* ```
|
|
1432
|
+
*/
|
|
1433
|
+
static estimateSize<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): number;
|
|
1434
|
+
/**
|
|
1435
|
+
* 查找树中第一个满足条件的节点
|
|
1436
|
+
*
|
|
1437
|
+
* @category Data Structures
|
|
1438
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
1439
|
+
* @param predicate 查找条件函数
|
|
1440
|
+
* @param config 树形配置选项
|
|
1441
|
+
* @returns 匹配的节点;未找到时返回undefined
|
|
1442
|
+
* @example
|
|
1443
|
+
* ```ts
|
|
1444
|
+
* const tree = [
|
|
1445
|
+
* {
|
|
1446
|
+
* id: '1',
|
|
1447
|
+
* name: '部门1',
|
|
1448
|
+
* children: [
|
|
1449
|
+
* { id: '2', name: '部门1-1', children: [] }
|
|
1450
|
+
* ]
|
|
1451
|
+
* }
|
|
1452
|
+
* ]
|
|
1453
|
+
*
|
|
1454
|
+
* const result = Tree.find(tree, ({ node }) => node.name === '部门1-1')
|
|
1455
|
+
* console.log(result?.id) // '2'
|
|
1456
|
+
* ```
|
|
1457
|
+
*/
|
|
1458
|
+
static find<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNode<T> | undefined;
|
|
1459
|
+
/**
|
|
1460
|
+
* 查找树中所有满足条件的节点
|
|
1461
|
+
*
|
|
1462
|
+
* @category Data Structures
|
|
1463
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
1464
|
+
* @param predicate 查找条件函数
|
|
1465
|
+
* @param config 树形配置选项
|
|
1466
|
+
* @returns 所有匹配的节点数组
|
|
1467
|
+
* @example
|
|
1468
|
+
* ```ts
|
|
1469
|
+
* const tree = [
|
|
1470
|
+
* {
|
|
1471
|
+
* id: '1',
|
|
1472
|
+
* type: 'folder',
|
|
1473
|
+
* name: '根目录',
|
|
1474
|
+
* children: [
|
|
1475
|
+
* { id: '2', type: 'file', name: '文件1', children: [] },
|
|
1476
|
+
* { id: '3', type: 'file', name: '文件2', children: [] }
|
|
1477
|
+
* ]
|
|
1478
|
+
* }
|
|
1479
|
+
* ]
|
|
1480
|
+
*
|
|
1481
|
+
* const files = Tree.findAll(tree, ({ node }) => node.type === 'file')
|
|
1482
|
+
* console.log(files.length) // 2
|
|
1483
|
+
* ```
|
|
1484
|
+
*/
|
|
1485
|
+
static findAll<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNode<T>[];
|
|
1486
|
+
/**
|
|
1487
|
+
* 根据ID查找树中的节点
|
|
1488
|
+
*
|
|
1489
|
+
* @category Data Structures
|
|
1490
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
1491
|
+
* @param id 要查找的节点ID
|
|
1492
|
+
* @param config 树形配置选项
|
|
1493
|
+
* @returns 匹配的节点;未找到时返回undefined
|
|
1494
|
+
* @example
|
|
1495
|
+
* ```ts
|
|
1496
|
+
* const tree = [
|
|
1497
|
+
* {
|
|
1498
|
+
* id: '1',
|
|
1499
|
+
* name: '根节点',
|
|
1500
|
+
* children: [
|
|
1501
|
+
* { id: '2', name: '子节点', children: [] }
|
|
1502
|
+
* ]
|
|
1503
|
+
* }
|
|
1504
|
+
* ]
|
|
1505
|
+
*
|
|
1506
|
+
* const result = Tree.findById(tree, '2')
|
|
1507
|
+
* console.log(result?.name) // '子节点'
|
|
1508
|
+
* ```
|
|
1509
|
+
*/
|
|
1510
|
+
static findById<T = any>(tree: TreeNode<T> | TreeNode<T>[], id: string, config?: TreeConfigInput): TreeNode<T> | undefined;
|
|
1511
|
+
/**
|
|
1512
|
+
* 获取树形结构的统计信息
|
|
1513
|
+
*
|
|
1514
|
+
* @category Data Structures
|
|
1515
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
1516
|
+
* @param config 树形配置选项
|
|
1517
|
+
* @returns 树的统计信息,包含总节点数、叶子节点数、最大深度和分支节点数
|
|
1518
|
+
* @example
|
|
1519
|
+
* ```ts
|
|
1520
|
+
* const tree = [
|
|
1521
|
+
* {
|
|
1522
|
+
* id: '1',
|
|
1523
|
+
* name: '根节点',
|
|
1524
|
+
* children: [
|
|
1525
|
+
* { id: '2', name: '子节点1', children: [] },
|
|
1526
|
+
* { id: '3', name: '子节点2', children: [
|
|
1527
|
+
* { id: '4', name: '孙节点', children: [] }
|
|
1528
|
+
* ] }
|
|
1529
|
+
* ]
|
|
1530
|
+
* }
|
|
1531
|
+
* ]
|
|
1532
|
+
*
|
|
1533
|
+
* const stats = Tree.getStats(tree)
|
|
1534
|
+
* console.log(stats) // { total: 4, leaves: 2, depth: 3, branches: 2 }
|
|
1535
|
+
* ```
|
|
1536
|
+
*/
|
|
1537
|
+
static getStats<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): TreeStats;
|
|
1538
|
+
/**
|
|
1539
|
+
* 过滤树形结构,保留满足条件的节点及其祖先和后代
|
|
1540
|
+
*
|
|
1541
|
+
* @category Data Structures
|
|
1542
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
1543
|
+
* @param predicate 过滤条件函数,接收对象参数 {node, depth, path, index}
|
|
1544
|
+
* @param config 树形配置选项
|
|
1545
|
+
* @returns 过滤后的树形结构数组
|
|
1546
|
+
* @example
|
|
1547
|
+
* ```ts
|
|
1548
|
+
* const tree = [
|
|
1549
|
+
* {
|
|
1550
|
+
* id: '1',
|
|
1551
|
+
* type: 'folder',
|
|
1552
|
+
* name: '根目录',
|
|
1553
|
+
* children: [
|
|
1554
|
+
* { id: '2', type: 'file', name: '文档.txt', children: [] },
|
|
1555
|
+
* { id: '3', type: 'folder', name: '子目录', children: [
|
|
1556
|
+
* { id: '4', type: 'file', name: '图片.jpg', children: [] }
|
|
1557
|
+
* ] }
|
|
1558
|
+
* ]
|
|
1559
|
+
* }
|
|
1560
|
+
* ]
|
|
1561
|
+
*
|
|
1562
|
+
* const filtered = Tree.filter(tree, ({ node }) => node.type === 'file')
|
|
1563
|
+
* // 返回包含所有文件节点及其父级路径的树结构
|
|
1564
|
+
* ```
|
|
1565
|
+
*/
|
|
1566
|
+
static filter<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNode<T>[];
|
|
1567
|
+
/**
|
|
1568
|
+
* 转换树形结构,将每个节点转换为新的结构
|
|
1569
|
+
*
|
|
1570
|
+
* @category Data Structures
|
|
1571
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
1572
|
+
* @param transformer 节点转换函数,接收对象参数 {node, depth, path, index}
|
|
1573
|
+
* @param config 树形配置选项
|
|
1574
|
+
* @returns 转换后的树形结构数组
|
|
1575
|
+
* @example
|
|
1576
|
+
* ```ts
|
|
1577
|
+
* const tree = [
|
|
1578
|
+
* {
|
|
1579
|
+
* id: '1',
|
|
1580
|
+
* name: '部门1',
|
|
1581
|
+
* children: [
|
|
1582
|
+
* { id: '2', name: '部门1-1', children: [] }
|
|
1583
|
+
* ]
|
|
1584
|
+
* }
|
|
1585
|
+
* ]
|
|
1586
|
+
*
|
|
1587
|
+
* const transformed = Tree.transform(tree, ({ node, depth }) => ({
|
|
1588
|
+
* key: node.id,
|
|
1589
|
+
* title: node.name,
|
|
1590
|
+
* level: depth
|
|
1591
|
+
* }))
|
|
1592
|
+
* // 转换为新的数据结构
|
|
1593
|
+
* ```
|
|
1594
|
+
*/
|
|
1595
|
+
static transform<T = any, R = any>(tree: TreeNode<T> | TreeNode<T>[], transformer: TreeTransformer<T, R>, config?: TreeConfigInput): TreeNode<R>[];
|
|
1596
|
+
/**
|
|
1597
|
+
* 遍历树形结构的每个节点
|
|
1598
|
+
*
|
|
1599
|
+
* @category Data Structures
|
|
1600
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
1601
|
+
* @param visitor 访问者函数,接收对象参数 {node, depth, path, index},返回false可以跳过子节点的遍历
|
|
1602
|
+
* @param config 树形配置选项
|
|
1603
|
+
* @example
|
|
1604
|
+
* ```ts
|
|
1605
|
+
* const tree = [
|
|
1606
|
+
* {
|
|
1607
|
+
* id: '1',
|
|
1608
|
+
* name: '根节点',
|
|
1609
|
+
* children: [
|
|
1610
|
+
* { id: '2', name: '子节点', children: [] }
|
|
1611
|
+
* ]
|
|
1612
|
+
* }
|
|
1613
|
+
* ]
|
|
1614
|
+
*
|
|
1615
|
+
* Tree.forEach(tree, ({ node, depth }) => {
|
|
1616
|
+
* console.log(`${' '.repeat(depth * 2)}${node.name}`)
|
|
1617
|
+
* // 输出缩进的树结构
|
|
1618
|
+
* })
|
|
1619
|
+
* ```
|
|
1620
|
+
*/
|
|
1621
|
+
static forEach<T = any>(tree: TreeNode<T> | TreeNode<T>[], visitor: TreeVisitor<T>, config?: TreeConfigInput): void;
|
|
1622
|
+
/**
|
|
1623
|
+
* 在指定节点前插入新节点
|
|
1624
|
+
*
|
|
1625
|
+
* @category Data Structures
|
|
1626
|
+
* @param tree 树形结构数组
|
|
1627
|
+
* @param targetId 目标节点的ID
|
|
1628
|
+
* @param newNode 要插入的新节点数据
|
|
1629
|
+
* @param config 树形配置选项
|
|
1630
|
+
* @returns 是否成功插入
|
|
1631
|
+
* @example
|
|
1632
|
+
* ```ts
|
|
1633
|
+
* const tree = [
|
|
1634
|
+
* {
|
|
1635
|
+
* id: '1',
|
|
1636
|
+
* name: '节点1',
|
|
1637
|
+
* children: [
|
|
1638
|
+
* { id: '2', name: '节点2', children: [] }
|
|
1639
|
+
* ]
|
|
1640
|
+
* }
|
|
1641
|
+
* ]
|
|
1642
|
+
*
|
|
1643
|
+
* const success = Tree.insertBefore(tree, '2', { id: '1.5', name: '新节点' })
|
|
1644
|
+
* console.log(success) // true
|
|
1645
|
+
* ```
|
|
1646
|
+
*/
|
|
1647
|
+
static insertBefore<T = any>(tree: TreeNode<T>[], targetId: string, newNode: T, config?: TreeConfigInput): boolean;
|
|
1648
|
+
/**
|
|
1649
|
+
* 在指定节点后插入新节点
|
|
1650
|
+
*
|
|
1651
|
+
* @category Data Structures
|
|
1652
|
+
* @param tree 树形结构数组
|
|
1653
|
+
* @param targetId 目标节点的ID
|
|
1654
|
+
* @param newNode 要插入的新节点数据
|
|
1655
|
+
* @param config 树形配置选项
|
|
1656
|
+
* @returns 是否成功插入
|
|
1657
|
+
* @example
|
|
1658
|
+
* ```ts
|
|
1659
|
+
* const tree = [
|
|
1660
|
+
* {
|
|
1661
|
+
* id: '1',
|
|
1662
|
+
* name: '节点1',
|
|
1663
|
+
* children: [
|
|
1664
|
+
* { id: '2', name: '节点2', children: [] }
|
|
1665
|
+
* ]
|
|
1666
|
+
* }
|
|
1667
|
+
* ]
|
|
1668
|
+
*
|
|
1669
|
+
* const success = Tree.insertAfter(tree, '2', { id: '3', name: '新节点' })
|
|
1670
|
+
* console.log(success) // true
|
|
1671
|
+
* ```
|
|
1672
|
+
*/
|
|
1673
|
+
static insertAfter<T = any>(tree: TreeNode<T>[], targetId: string, newNode: T, config?: TreeConfigInput): boolean;
|
|
1674
|
+
/**
|
|
1675
|
+
* 从树中删除指定节点
|
|
1676
|
+
*
|
|
1677
|
+
* @category Data Structures
|
|
1678
|
+
* @param tree 树形结构数组
|
|
1679
|
+
* @param targetId 要删除的节点ID
|
|
1680
|
+
* @param config 树形配置选项
|
|
1681
|
+
* @returns 被删除的节点,未找到时返回undefined
|
|
1682
|
+
* @example
|
|
1683
|
+
* ```ts
|
|
1684
|
+
* const tree = [
|
|
1685
|
+
* {
|
|
1686
|
+
* id: '1',
|
|
1687
|
+
* name: '根节点',
|
|
1688
|
+
* children: [
|
|
1689
|
+
* { id: '2', name: '子节点', children: [] }
|
|
1690
|
+
* ]
|
|
1691
|
+
* }
|
|
1692
|
+
* ]
|
|
1693
|
+
*
|
|
1694
|
+
* const removed = Tree.remove(tree, '2')
|
|
1695
|
+
* console.log(removed?.name) // '子节点'
|
|
1696
|
+
* ```
|
|
1697
|
+
*/
|
|
1698
|
+
static remove<T = any>(tree: TreeNode<T>[], targetId: string, config?: TreeConfigInput): TreeNode<T> | undefined;
|
|
1699
|
+
/**
|
|
1700
|
+
* 验证树形结构的有效性
|
|
1701
|
+
*
|
|
1702
|
+
* @category Data Structures
|
|
1703
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
1704
|
+
* @param config 树形配置选项
|
|
1705
|
+
* @returns 验证结果,包含是否有效和错误信息数组
|
|
1706
|
+
* @example
|
|
1707
|
+
* ```ts
|
|
1708
|
+
* const tree = [
|
|
1709
|
+
* {
|
|
1710
|
+
* id: '1',
|
|
1711
|
+
* name: '根节点',
|
|
1712
|
+
* children: [
|
|
1713
|
+
* { id: '2', name: '子节点', children: [] }
|
|
1714
|
+
* ]
|
|
1715
|
+
* }
|
|
1716
|
+
* ]
|
|
1717
|
+
*
|
|
1718
|
+
* const result = Tree.validate(tree)
|
|
1719
|
+
* console.log(result.isValid) // true
|
|
1720
|
+
* console.log(result.errors) // []
|
|
1721
|
+
* ```
|
|
1722
|
+
*/
|
|
1723
|
+
static validate<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): {
|
|
1724
|
+
isValid: boolean;
|
|
1725
|
+
errors: string[];
|
|
1726
|
+
};
|
|
1727
|
+
}
|
|
1206
1728
|
|
|
1207
1729
|
/**
|
|
1208
1730
|
* 生成字符串的简单哈希值
|
|
@@ -1338,6 +1860,21 @@ declare function isFunction(value: any): value is (...args: any[]) => any;
|
|
|
1338
1860
|
* ```
|
|
1339
1861
|
*/
|
|
1340
1862
|
declare function isEmpty(value: any): boolean;
|
|
1863
|
+
/**
|
|
1864
|
+
* 判断值是否为纯对象(不包括数组、函数、日期等)
|
|
1865
|
+
*
|
|
1866
|
+
* @category Object
|
|
1867
|
+
* @param value 要检查的值
|
|
1868
|
+
* @returns 是否为纯对象
|
|
1869
|
+
* @example
|
|
1870
|
+
* ```ts
|
|
1871
|
+
* isPlainObject({}) // true
|
|
1872
|
+
* isPlainObject([]) // false
|
|
1873
|
+
* isPlainObject(new Date()) // false
|
|
1874
|
+
* isPlainObject(() => {}) // false
|
|
1875
|
+
* ```
|
|
1876
|
+
*/
|
|
1877
|
+
declare function isPlainObject(value: unknown): value is Record<string, any>;
|
|
1341
1878
|
|
|
1342
|
-
export { StorageTypeSchema, Tree, camelToKebab, capitalize, chunk, convertSvgToPng, convertToKebabCase, createStorageConfigSchema, debounce, deepClone, extractFilename, flatten, formatFileSize, getRandomUUID, isArray, isEmpty, isFunction, isNumber, isObject, isString, kebabToCamel, omit, omitUndefined, pick, replaceCurrentColor, separate, separateMany, simpleHash, sleep, sleepWithCancel, throttle, triggerDownload, unique, useAppStorage, useCopyCode };
|
|
1343
|
-
export type { AnyObject, ApiAwaitable, ApiAwaitedReturn, ApiUnwrapPromise, AppStorageReturn, DeepPartial, FirstParam, FirstParameter, GetObjectField, MutableByKeys, OmitByKey, PartialByKeys, PickByKey, ReadonlyByKeys, RenameKeys, RequiredByKeys, StorageConfig, StorageConfigInput, StorageType, StringOrVNode, UnionToIntersection, UnknownObject };
|
|
1879
|
+
export { StorageTypeSchema, Tree, camelCase, camelToKebab, capitalize, chunk, convertSvgToPng, convertToKebabCase, createStorageConfigSchema, debounce, deepClone, extractFilename, flatten, formatFileSize, getPath, getRandomUUID, isArray, isEmpty, isFunction, isNumber, isObject, isPlainObject, isString, isValidContainer, joinPath, kebabCase, kebabToCamel, lowerCase, lowerFirst, omit, omitUndefined, pascalCase, pick, replaceCurrentColor, separate, separateMany, setPath, simpleHash, sleep, sleepWithCancel, snakeCase, startCase, throttle, toPath, triggerDownload, unique, upperCase, upperFirst, useAppStorage, useCopyCode, words };
|
|
1880
|
+
export type { AnyObject, ApiAwaitable, ApiAwaitedReturn, ApiUnwrapPromise, AppStorageReturn, ArrayFieldKeys, ComponentAttrs, ComponentEmit, ComponentExposed, ComponentProps, ComponentSlots, ComponentType, DeepPartial, FirstParam, FirstParameter, GetFieldValue, GetObjectField, IsComponent, IsPlainObject, Merge, MutableByKeys, NestedKeys, NonObjectFieldKeys, ObjectFieldKeys, OmitByKey, PartialByKeys, PickByKey, ReactiveValue, ReadonlyByKeys, RenameKeys, RequiredByKeys, StorageConfig, StorageConfigInput, StorageType, StringOrVNode, StripNullable, Suggest, UnionToIntersection, UnknownObject };
|