@gateweb/react-utils 1.5.0 → 1.7.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.
@@ -423,6 +423,55 @@ declare const pick: <T extends object, K extends [...(keyof T)[]]>(object: T, ..
423
423
  * const b = pickByValue(a, 1, 2); // { a: 1, b: 2 }
424
424
  */
425
425
  declare const pickByValue: <T extends object, K extends any[]>(object: T, ...values: K) => Pick<T, { [K2 in keyof T]: T[K2] extends K[number] ? K2 : never; }[keyof T]>;
426
+ /**
427
+ * merge two objects deeply
428
+ *
429
+ * @param target - the target object
430
+ * @param source - the source object
431
+ *
432
+ * @example
433
+ *
434
+ * const obja = { a: { a1: { a11: 'value 1', a12: 'value 2' }, a2: 'value 3' }, b: 'value 4' };
435
+ * const objb = { a: { a1: { a13: 'value 5', a14: 'value 6' }, a3: 'value 7' }};
436
+ *
437
+ * const mergeResult = deepMerge(obja, objb); // { a: { a1: { a11: 'value 1', a12: 'value 2', a13: 'value 5', a14: 'value 6' }, a2: 'value 3', a3: 'value 7' }, b: 'value 4' }
438
+ *
439
+ */
440
+ declare const deepMerge: <T extends object, U extends object>(target: T, source: U) => T & U;
441
+ /**
442
+ * a utility type to make all properties of an object required
443
+ *
444
+ * @param T - the object type
445
+ * @param K - the keys to make required
446
+ * @param RemoveUndefined - whether to remove undefined from the type
447
+ *
448
+ * @example
449
+ *
450
+ * type A = { a?: number; b?: string | undefined; c?: boolean };
451
+ * // Even though b is required, it can be undefined
452
+ * type B = RequiredBy<A, 'a' | 'b'>; // { a: number; b: string | undefined; c?: boolean
453
+ * type C = RequiredBy<A, 'a' | 'b', true>; // { a: number; b: string; c?: boolean }
454
+ */
455
+ type RequiredBy<T, K extends keyof T, RemoveUndefined extends boolean = false> = Omit<T, K> & {
456
+ [P in K]-?: RemoveUndefined extends true ? Exclude<T[P], undefined> : T[P];
457
+ };
458
+ /**
459
+ * a utility type to make all properties of an object optional
460
+ *
461
+ * @param T - the object type
462
+ * @param K - the keys to make optional
463
+ * @param RemoveUndefined - whether to remove undefined from the type
464
+ *
465
+ * @example
466
+ *
467
+ * type A = { a: number; b: string | undefined; c: boolean };
468
+ * // Even though b is optional, it can be undefined
469
+ * type B = PartialBy<A, 'a' | 'b'>; // { a?: number; b?: string | undefined; c: boolean }
470
+ * type C = PartialBy<A, 'a' | 'b', true>; // { a?: number; b?: string; c: boolean }
471
+ */
472
+ type PartialBy<T, K extends keyof T, RemoveUndefined extends boolean = false> = Omit<T, K> & {
473
+ [P in K]?: RemoveUndefined extends true ? Exclude<T[P], undefined> : T[P];
474
+ };
426
475
 
427
476
  /**
428
477
  * debounce function
@@ -812,4 +861,5 @@ declare const getLocalStorage: <T>(key: string, deCode?: boolean) => T | undefin
812
861
  */
813
862
  declare const setLocalStorage: (key: string, value: Record<string, any>, enCode?: boolean) => void;
814
863
 
815
- export { type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useValue, validTaxId, validateDateString, validateFileType, wait };
864
+ export { adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, deepMerge, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useValue, validTaxId, validateDateString, validateFileType, wait };
865
+ export type { PartialBy, RequiredBy, TCountdownActions };
package/dist/cjs/index.js CHANGED
@@ -602,6 +602,30 @@ message) {
602
602
  }
603
603
  return acc;
604
604
  }, {});
605
+ const isObject = (value)=>value !== null && typeof value === 'object';
606
+ /**
607
+ * merge two objects deeply
608
+ *
609
+ * @param target - the target object
610
+ * @param source - the source object
611
+ *
612
+ * @example
613
+ *
614
+ * const obja = { a: { a1: { a11: 'value 1', a12: 'value 2' }, a2: 'value 3' }, b: 'value 4' };
615
+ * const objb = { a: { a1: { a13: 'value 5', a14: 'value 6' }, a3: 'value 7' }};
616
+ *
617
+ * const mergeResult = deepMerge(obja, objb); // { a: { a1: { a11: 'value 1', a12: 'value 2', a13: 'value 5', a14: 'value 6' }, a2: 'value 3', a3: 'value 7' }, b: 'value 4' }
618
+ *
619
+ */ const deepMerge = (target, source)=>Object.entries(source).reduce((acc, [key, value])=>{
620
+ if (isObject(value)) {
621
+ acc[key] = key in target && isObject(target[key]) ? deepMerge(target[key], value) : value;
622
+ } else {
623
+ acc[key] = value;
624
+ }
625
+ return acc;
626
+ }, {
627
+ ...target
628
+ });
605
629
 
606
630
  /**
607
631
  * debounce function
@@ -917,6 +941,7 @@ exports.camelString2PascalString = camelString2PascalString;
917
941
  exports.camelString2SnakeString = camelString2SnakeString;
918
942
  exports.createEnumLikeObject = createEnumLikeObject;
919
943
  exports.debounce = debounce;
944
+ exports.deepMerge = deepMerge;
920
945
  exports.extractEnumLikeObject = extractEnumLikeObject;
921
946
  exports.fakeApi = fakeApi;
922
947
  exports.formatAmount = formatAmount;
@@ -1,3 +1,50 @@
1
+ /**
2
+ * A utility type that shifts the first argument of a function type `T` and returns the new function type.
3
+ *
4
+ * @template T - The function type to shift the first argument.
5
+ *
6
+ * @example
7
+ *
8
+ * type Example = (arg1: string, arg2: number) => boolean;
9
+ * type ShiftedExample = ShiftArgs<Example>; // ShiftedExample is (arg2: number) => boolean;
10
+ */
11
+ type ShiftArgs<T extends (...args: any) => any> = T extends (arg1: any, ...rest: infer P) => infer R ? (...args: P) => R : never;
12
+ /**
13
+ * A utility type that pops the last argument of a function type `T` and returns the new function type.
14
+ *
15
+ * @template T - The function type to pop the last argument.
16
+ *
17
+ * @example
18
+ *
19
+ * type Example = (arg1: string, arg2: number) => boolean;
20
+ * type PoppedExample = PopArgs<Example>; // PoppedExample is (arg1: string) => boolean;
21
+ */
22
+ type PopArgs<T extends (...args: any) => any> = T extends (...args: [...infer P, any]) => infer R ? (...args: P) => R : never;
23
+ /**
24
+ * A utility type that pushes a new argument of type `A` to the end of a function type `T` and returns the new function type.
25
+ *
26
+ * @template T - The function type to push the new argument.
27
+ * @template A - The new argument type to push.
28
+ *
29
+ * @example
30
+ *
31
+ * type Example = (arg1: string, arg2: number) => boolean;
32
+ * type PushedExample = PushArgs<Example, boolean>; // PushedExample is (arg1: string, arg2: number, arg3: boolean) => boolean;
33
+ */
34
+ type PushArgs<T extends (...args: any) => any, A> = T extends (...args: infer P) => infer R ? (...args: [...P, A]) => R : never;
35
+ /**
36
+ * A utility type that unshift a new argument of type `A` to the beginning of a function type `T` and returns the new function type.
37
+ *
38
+ * @template T - The function type to unshift the new argument.
39
+ * @template A - The new argument type to unshift.
40
+ *
41
+ * @example
42
+ *
43
+ * type Example = (arg1: string, arg2: number) => boolean;
44
+ * type UnshiftExample = UnshiftArgs<Example, boolean>; // UnshiftExample is (arg3: boolean, arg1: string, arg2: number) => boolean;
45
+ */
46
+ type UnshiftArgs<T extends (...args: any) => any, A> = T extends (...args: infer P) => infer R ? (...args: [A, ...P]) => R : never;
47
+
1
48
  /**
2
49
  * 從對象類型中提取特定屬性的值類型。
3
50
  *
@@ -41,6 +88,8 @@ type Entries<T> = {
41
88
  *
42
89
  * @template T - The object type to transform into keys.
43
90
  *
91
+ * @deprecated Use `MapToType` instead.
92
+ *
44
93
  * @example
45
94
  *
46
95
  * type Example = { a: number; b: string };
@@ -88,5 +137,55 @@ type OnlyOne<T> = {
88
137
  [P in Exclude<keyof T, K>]?: never;
89
138
  };
90
139
  }[keyof T];
140
+ /**
141
+ * A utility type that makes all properties in the generic type `T` optional. Also, it makes all nested properties optional.
142
+ *
143
+ * @template T - The object type to make all properties optional.
144
+ *
145
+ * @example
146
+ *
147
+ * type Example = { a: string; b: number };
148
+ * type ExamplePartial = DeepPartial<Example>;
149
+ *
150
+ * const obj: ExamplePartial = { a: 'hello' }; // OK
151
+ *
152
+ * type ExampleDeep = { a: { b: string; c: number } };
153
+ * type ExampleDeepPartial = DeepPartial<ExampleDeep>;
154
+ *
155
+ * const obj2: ExampleDeepPartial = { a: { b: 'world' } }; // OK
156
+ */
157
+ type DeepPartial<T> = (T extends (infer U)[] ? DeepPartial<U>[] : {
158
+ [P in keyof T]?: DeepPartial<T[P]>;
159
+ }) | T;
160
+ /**
161
+ * 將 Obj 指定的 key 轉換成指定的型別
162
+ *
163
+ * @example
164
+ *
165
+ * ```ts
166
+ * type Obj = { a: string, b: number, c: boolean}
167
+ *
168
+ * type NewObj = TChangeKeyType<Obj, 'b', string> // { a: string, b: string, c: boolean }
169
+ *
170
+ * type NewObj2 = TChangeKeyType<Obj, 'b' | 'c', string> // { a: string, b: string, c: string }
171
+ * ```
172
+ */
173
+ type TChangeKeyType<T, K extends keyof T, V> = Omit<T, K> & {
174
+ [P in K]: V;
175
+ };
176
+ /**
177
+ * A utility type that transforms an object type `T` into another object type where each value type is replaced with type `A`.
178
+ *
179
+ * @template T - The object type to transform into keys.
180
+ *
181
+ * @example
182
+ *
183
+ * type Example = { a: number; b: string };
184
+ * type ExampleToBoolean = MapToType<Example, boolean>;
185
+ * // Result: ExampleToBoolean is { a: boolean; b: boolean; }
186
+ */
187
+ type MapToType<T extends Record<any, any>, A = any> = {
188
+ [K in keyof T]: A;
189
+ };
91
190
 
92
- export type { AtLeastOne, Entries, MapToString, OnlyOne, TExtractValueType };
191
+ export type { AtLeastOne, DeepPartial, Entries, MapToString, MapToType, OnlyOne, PopArgs, PushArgs, ShiftArgs, TChangeKeyType, TExtractValueType, UnshiftArgs };
@@ -423,6 +423,55 @@ declare const pick: <T extends object, K extends [...(keyof T)[]]>(object: T, ..
423
423
  * const b = pickByValue(a, 1, 2); // { a: 1, b: 2 }
424
424
  */
425
425
  declare const pickByValue: <T extends object, K extends any[]>(object: T, ...values: K) => Pick<T, { [K2 in keyof T]: T[K2] extends K[number] ? K2 : never; }[keyof T]>;
426
+ /**
427
+ * merge two objects deeply
428
+ *
429
+ * @param target - the target object
430
+ * @param source - the source object
431
+ *
432
+ * @example
433
+ *
434
+ * const obja = { a: { a1: { a11: 'value 1', a12: 'value 2' }, a2: 'value 3' }, b: 'value 4' };
435
+ * const objb = { a: { a1: { a13: 'value 5', a14: 'value 6' }, a3: 'value 7' }};
436
+ *
437
+ * const mergeResult = deepMerge(obja, objb); // { a: { a1: { a11: 'value 1', a12: 'value 2', a13: 'value 5', a14: 'value 6' }, a2: 'value 3', a3: 'value 7' }, b: 'value 4' }
438
+ *
439
+ */
440
+ declare const deepMerge: <T extends object, U extends object>(target: T, source: U) => T & U;
441
+ /**
442
+ * a utility type to make all properties of an object required
443
+ *
444
+ * @param T - the object type
445
+ * @param K - the keys to make required
446
+ * @param RemoveUndefined - whether to remove undefined from the type
447
+ *
448
+ * @example
449
+ *
450
+ * type A = { a?: number; b?: string | undefined; c?: boolean };
451
+ * // Even though b is required, it can be undefined
452
+ * type B = RequiredBy<A, 'a' | 'b'>; // { a: number; b: string | undefined; c?: boolean
453
+ * type C = RequiredBy<A, 'a' | 'b', true>; // { a: number; b: string; c?: boolean }
454
+ */
455
+ type RequiredBy<T, K extends keyof T, RemoveUndefined extends boolean = false> = Omit<T, K> & {
456
+ [P in K]-?: RemoveUndefined extends true ? Exclude<T[P], undefined> : T[P];
457
+ };
458
+ /**
459
+ * a utility type to make all properties of an object optional
460
+ *
461
+ * @param T - the object type
462
+ * @param K - the keys to make optional
463
+ * @param RemoveUndefined - whether to remove undefined from the type
464
+ *
465
+ * @example
466
+ *
467
+ * type A = { a: number; b: string | undefined; c: boolean };
468
+ * // Even though b is optional, it can be undefined
469
+ * type B = PartialBy<A, 'a' | 'b'>; // { a?: number; b?: string | undefined; c: boolean }
470
+ * type C = PartialBy<A, 'a' | 'b', true>; // { a?: number; b?: string; c: boolean }
471
+ */
472
+ type PartialBy<T, K extends keyof T, RemoveUndefined extends boolean = false> = Omit<T, K> & {
473
+ [P in K]?: RemoveUndefined extends true ? Exclude<T[P], undefined> : T[P];
474
+ };
426
475
 
427
476
  /**
428
477
  * debounce function
@@ -812,4 +861,5 @@ declare const getLocalStorage: <T>(key: string, deCode?: boolean) => T | undefin
812
861
  */
813
862
  declare const setLocalStorage: (key: string, value: Record<string, any>, enCode?: boolean) => void;
814
863
 
815
- export { type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useValue, validTaxId, validateDateString, validateFileType, wait };
864
+ export { adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, deepMerge, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useValue, validTaxId, validateDateString, validateFileType, wait };
865
+ export type { PartialBy, RequiredBy, TCountdownActions };
package/dist/es/index.mjs CHANGED
@@ -596,6 +596,30 @@ message) {
596
596
  }
597
597
  return acc;
598
598
  }, {});
599
+ const isObject = (value)=>value !== null && typeof value === 'object';
600
+ /**
601
+ * merge two objects deeply
602
+ *
603
+ * @param target - the target object
604
+ * @param source - the source object
605
+ *
606
+ * @example
607
+ *
608
+ * const obja = { a: { a1: { a11: 'value 1', a12: 'value 2' }, a2: 'value 3' }, b: 'value 4' };
609
+ * const objb = { a: { a1: { a13: 'value 5', a14: 'value 6' }, a3: 'value 7' }};
610
+ *
611
+ * const mergeResult = deepMerge(obja, objb); // { a: { a1: { a11: 'value 1', a12: 'value 2', a13: 'value 5', a14: 'value 6' }, a2: 'value 3', a3: 'value 7' }, b: 'value 4' }
612
+ *
613
+ */ const deepMerge = (target, source)=>Object.entries(source).reduce((acc, [key, value])=>{
614
+ if (isObject(value)) {
615
+ acc[key] = key in target && isObject(target[key]) ? deepMerge(target[key], value) : value;
616
+ } else {
617
+ acc[key] = value;
618
+ }
619
+ return acc;
620
+ }, {
621
+ ...target
622
+ });
599
623
 
600
624
  /**
601
625
  * debounce function
@@ -900,4 +924,4 @@ function mergeRefs(refs) {
900
924
  */ const wait = (ms)=>{
901
925
  };
902
926
 
903
- export { adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useValue, validTaxId, validateDateString, validateFileType, wait };
927
+ export { adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, deepMerge, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useValue, validTaxId, validateDateString, validateFileType, wait };
@@ -1,3 +1,50 @@
1
+ /**
2
+ * A utility type that shifts the first argument of a function type `T` and returns the new function type.
3
+ *
4
+ * @template T - The function type to shift the first argument.
5
+ *
6
+ * @example
7
+ *
8
+ * type Example = (arg1: string, arg2: number) => boolean;
9
+ * type ShiftedExample = ShiftArgs<Example>; // ShiftedExample is (arg2: number) => boolean;
10
+ */
11
+ type ShiftArgs<T extends (...args: any) => any> = T extends (arg1: any, ...rest: infer P) => infer R ? (...args: P) => R : never;
12
+ /**
13
+ * A utility type that pops the last argument of a function type `T` and returns the new function type.
14
+ *
15
+ * @template T - The function type to pop the last argument.
16
+ *
17
+ * @example
18
+ *
19
+ * type Example = (arg1: string, arg2: number) => boolean;
20
+ * type PoppedExample = PopArgs<Example>; // PoppedExample is (arg1: string) => boolean;
21
+ */
22
+ type PopArgs<T extends (...args: any) => any> = T extends (...args: [...infer P, any]) => infer R ? (...args: P) => R : never;
23
+ /**
24
+ * A utility type that pushes a new argument of type `A` to the end of a function type `T` and returns the new function type.
25
+ *
26
+ * @template T - The function type to push the new argument.
27
+ * @template A - The new argument type to push.
28
+ *
29
+ * @example
30
+ *
31
+ * type Example = (arg1: string, arg2: number) => boolean;
32
+ * type PushedExample = PushArgs<Example, boolean>; // PushedExample is (arg1: string, arg2: number, arg3: boolean) => boolean;
33
+ */
34
+ type PushArgs<T extends (...args: any) => any, A> = T extends (...args: infer P) => infer R ? (...args: [...P, A]) => R : never;
35
+ /**
36
+ * A utility type that unshift a new argument of type `A` to the beginning of a function type `T` and returns the new function type.
37
+ *
38
+ * @template T - The function type to unshift the new argument.
39
+ * @template A - The new argument type to unshift.
40
+ *
41
+ * @example
42
+ *
43
+ * type Example = (arg1: string, arg2: number) => boolean;
44
+ * type UnshiftExample = UnshiftArgs<Example, boolean>; // UnshiftExample is (arg3: boolean, arg1: string, arg2: number) => boolean;
45
+ */
46
+ type UnshiftArgs<T extends (...args: any) => any, A> = T extends (...args: infer P) => infer R ? (...args: [A, ...P]) => R : never;
47
+
1
48
  /**
2
49
  * 從對象類型中提取特定屬性的值類型。
3
50
  *
@@ -41,6 +88,8 @@ type Entries<T> = {
41
88
  *
42
89
  * @template T - The object type to transform into keys.
43
90
  *
91
+ * @deprecated Use `MapToType` instead.
92
+ *
44
93
  * @example
45
94
  *
46
95
  * type Example = { a: number; b: string };
@@ -88,5 +137,55 @@ type OnlyOne<T> = {
88
137
  [P in Exclude<keyof T, K>]?: never;
89
138
  };
90
139
  }[keyof T];
140
+ /**
141
+ * A utility type that makes all properties in the generic type `T` optional. Also, it makes all nested properties optional.
142
+ *
143
+ * @template T - The object type to make all properties optional.
144
+ *
145
+ * @example
146
+ *
147
+ * type Example = { a: string; b: number };
148
+ * type ExamplePartial = DeepPartial<Example>;
149
+ *
150
+ * const obj: ExamplePartial = { a: 'hello' }; // OK
151
+ *
152
+ * type ExampleDeep = { a: { b: string; c: number } };
153
+ * type ExampleDeepPartial = DeepPartial<ExampleDeep>;
154
+ *
155
+ * const obj2: ExampleDeepPartial = { a: { b: 'world' } }; // OK
156
+ */
157
+ type DeepPartial<T> = (T extends (infer U)[] ? DeepPartial<U>[] : {
158
+ [P in keyof T]?: DeepPartial<T[P]>;
159
+ }) | T;
160
+ /**
161
+ * 將 Obj 指定的 key 轉換成指定的型別
162
+ *
163
+ * @example
164
+ *
165
+ * ```ts
166
+ * type Obj = { a: string, b: number, c: boolean}
167
+ *
168
+ * type NewObj = TChangeKeyType<Obj, 'b', string> // { a: string, b: string, c: boolean }
169
+ *
170
+ * type NewObj2 = TChangeKeyType<Obj, 'b' | 'c', string> // { a: string, b: string, c: string }
171
+ * ```
172
+ */
173
+ type TChangeKeyType<T, K extends keyof T, V> = Omit<T, K> & {
174
+ [P in K]: V;
175
+ };
176
+ /**
177
+ * A utility type that transforms an object type `T` into another object type where each value type is replaced with type `A`.
178
+ *
179
+ * @template T - The object type to transform into keys.
180
+ *
181
+ * @example
182
+ *
183
+ * type Example = { a: number; b: string };
184
+ * type ExampleToBoolean = MapToType<Example, boolean>;
185
+ * // Result: ExampleToBoolean is { a: boolean; b: boolean; }
186
+ */
187
+ type MapToType<T extends Record<any, any>, A = any> = {
188
+ [K in keyof T]: A;
189
+ };
91
190
 
92
- export type { AtLeastOne, Entries, MapToString, OnlyOne, TExtractValueType };
191
+ export type { AtLeastOne, DeepPartial, Entries, MapToString, MapToType, OnlyOne, PopArgs, PushArgs, ShiftArgs, TChangeKeyType, TExtractValueType, UnshiftArgs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gateweb/react-utils",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "React Utils for GateWeb",
5
5
  "homepage": "https://github.com/GatewebSolutions/react-utils",
6
6
  "files": [
@@ -37,7 +37,9 @@
37
37
  "dependencies": {
38
38
  "dayjs": "^1.11.13",
39
39
  "react": "^19.0.0",
40
- "react-dom": "^19.0.0"
40
+ "react-dom": "^19.0.0",
41
+ "use-sync-external-store": "^1.5.0",
42
+ "zustand": "^5.0.3"
41
43
  },
42
44
  "devDependencies": {
43
45
  "@commitlint/cli": "^19.5.0",