@zelgadis87/utils-core 5.0.3 → 5.1.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "@zelgadis87/utils-core",
4
- "version": "5.0.3",
4
+ "version": "5.1.0",
5
5
  "author": "Zelgadis87",
6
6
  "license": "ISC",
7
7
  "private": false,
package/src/Optional.ts CHANGED
@@ -33,6 +33,13 @@ export class Optional<T> implements TOptional<T> {
33
33
  this._present = true;
34
34
  }
35
35
 
36
+ protected setNullable( t: T | null | undefined ) {
37
+ if ( isDefined( t ) ) {
38
+ return this.set( t );
39
+ }
40
+ return this;
41
+ }
42
+
36
43
  public clear() {
37
44
  this._value = undefined;
38
45
  this._present = false;
@@ -61,32 +68,78 @@ export class Optional<T> implements TOptional<T> {
61
68
  }
62
69
  }
63
70
 
64
- public orElse( newValue: T ) {
71
+ public orElseReturn( newValue: T ): T {
65
72
  if ( this.isPresent() ) {
66
- return this._value;
73
+ return this.get();
67
74
  } else {
68
75
  return newValue;
69
76
  }
70
77
  }
71
- public orElseGet( newValueProducer: TProducer<T> ) {
78
+ public orElse = this.orElseReturn.bind( this );
79
+
80
+ public orElseProduce( newValueProducer: TProducer<T> ): T {
72
81
  if ( this.isPresent() ) {
73
- return this._value;
82
+ return this.get();
74
83
  } else {
75
84
  return newValueProducer();
76
85
  }
77
86
  }
87
+ public orElseGet = this.orElseProduce.bind( this );
88
+
89
+ public orElseReturnAndApply( newValue: T ): T {
90
+ if ( this.isPresent() ) {
91
+ return this.get();
92
+ } else {
93
+ this.set( newValue );
94
+ return newValue;
95
+ }
96
+ }
97
+
98
+ public orElseProduceAndApply( newValueProducer: TProducer<T> ): T {
99
+ if ( this.isPresent() ) {
100
+ return this.get();
101
+ } else {
102
+ const newValue = newValueProducer();
103
+ this.set( newValue );
104
+ return newValue;
105
+ }
106
+ }
107
+
108
+ public orElseReturnNullableAndApply( newValue: T | null | undefined ): TOptional<T> {
109
+ if ( this.isPresent() ) {
110
+ return this;
111
+ } else {
112
+ this.setNullable( newValue );
113
+ return this;
114
+ }
115
+ }
116
+
117
+ public orElseProduceNullableAndApply( newValueProducer: TProducer<T | null | undefined> ): TOptional<T> {
118
+ if ( this.isPresent() ) {
119
+ return this;
120
+ } else {
121
+ const newValue = newValueProducer();
122
+ this.setNullable( newValue );
123
+ return this;
124
+ }
125
+ }
78
126
 
79
- public orElseNullable( newValue: T | null | undefined ) {
127
+ public orElseReturnNullable( newValue: T | null | undefined ) {
80
128
  if ( this.isEmpty() ) return Optional.ofNullable( newValue );
81
129
  return this as TPresentOptional<T>;
82
130
  }
83
- public orElseGetNullable( newValueProducer: TProducer<T | null | undefined> ) {
131
+ public orElseNullable = this.orElseReturnNullable.bind( this );
132
+
133
+
134
+ public orElseProduceNullable( newValueProducer: TProducer<T | null | undefined> ) {
84
135
  if ( this.isEmpty() ) {
85
136
  const newValue = newValueProducer();
86
137
  return Optional.ofNullable( newValue );
87
138
  }
88
139
  return this as TPresentOptional<T>;
89
140
  }
141
+ public orElseGetNullable = this.orElseProduceNullable.bind( this );
142
+
90
143
 
91
144
  public orElseThrow( errorProducer: TProducer<Error> ) {
92
145
  if ( this.isEmpty() )
@@ -127,24 +180,28 @@ export default Optional;
127
180
  export type TOptional<T> = {
128
181
 
129
182
  /**
130
- * @returns the currently stored value, if any; throws {@link ErrorGetEmptyOptional} otherwise;
131
- */
183
+ * @returns the currently stored value, if any; throws {@link ErrorGetEmptyOptional} otherwise;
184
+ */
132
185
  get(): T;
186
+
133
187
  /**
134
- * @returns the currently stored value, if any; returns undefined otherwise;
135
- */
188
+ * @returns the currently stored value, if any; returns undefined otherwise;
189
+ */
136
190
  getRawValue(): T | undefined;
191
+
137
192
  /**
138
- * @returns the currently stored value, if any; throws the error generated by errorProducer otherwise;
139
- */
193
+ * @returns the currently stored value, if any; throws the error generated by errorProducer otherwise;
194
+ */
140
195
  getOrElseThrow: ( errorProducer: TProducer<Error> ) => T;
196
+
141
197
  /**
142
- * Places a new value inside this optional. Throws {@link ErrorSetEmptyOptional} if t is null or undefined.
143
- */
198
+ * Places a new value inside this optional. Throws {@link ErrorSetEmptyOptional} if t is null or undefined.
199
+ */
144
200
  set( t: T ): void;
201
+
145
202
  /**
146
- * Clears the current value from this optional, if any.
147
- */
203
+ * Clears the current value from this optional, if any.
204
+ */
148
205
  clear(): void;
149
206
  isEmpty(): boolean;
150
207
  isPresent(): boolean;
@@ -153,10 +210,25 @@ export type TOptional<T> = {
153
210
  ifPresent: ( callback: TConsumer<T> ) => void;
154
211
  apply( callbackIfPresent: TConsumer<T>, callbackIfEmpty: TVoidFunction ): void;
155
212
 
213
+ /** @deprecated[2025.07.25]: Replace with {@link orElseReturn} (drop-in replacement) */
156
214
  orElse: ( newValue: T ) => T;
215
+ /** @deprecated[2025.07.25]: Replace with {@link orElseProduce} (drop-in replacement) */
157
216
  orElseGet: ( newValueProducer: TProducer<T> ) => T;
217
+ /** @deprecated[2025.07.25]: Replace with {@link orElseReturnNullabe} (drop-in replacement) */
158
218
  orElseNullable: ( newValue: T | null | undefined ) => TOptional<T>;
219
+ /** @deprecated[2025.07.25]: Replace with {@link orElseProduceNullable} (drop-in replacement) */
159
220
  orElseGetNullable: ( newValueProducer: TProducer<T | null | undefined> ) => TOptional<T>;
221
+
222
+ orElseReturn: ( newValue: T ) => T;
223
+ orElseProduce: ( newValueProducer: TProducer<T> ) => T;
224
+ orElseReturnNullable: ( newValue: T | null | undefined ) => TOptional<T>;
225
+ orElseProduceNullable: ( newValueProducer: TProducer<T | null | undefined> ) => TOptional<T>;
226
+
227
+ orElseReturnAndApply: ( newValue: T ) => T;
228
+ orElseProduceAndApply: ( newValueProducer: TProducer<T> ) => T;
229
+ orElseReturnNullableAndApply: ( newValue: T | null | undefined ) => TOptional<T>;
230
+ orElseProduceNullableAndApply: ( newValueProducer: TProducer<T | null | undefined> ) => TOptional<T>;
231
+
160
232
  orElseThrow: ( errorProducer: TProducer<Error> ) => TPresentOptional<T>;
161
233
 
162
234
  mapTo<R>( mapper: TFunction<T, R> ): TOptional<R>;
@@ -133,14 +133,32 @@ export function partition<T>( arr: T[], predicate: TPredicate<T> ): [ T[], T[] ]
133
133
  * @param mapFn - The mapping function.
134
134
  * @returns The first truthy value returned by the mapping function, or null if no truthy value is found.
135
135
  */
136
- export function mapFirstTruthy<T, R>(arr: T[], mapFn: TTransformer<T, R>): R | null {
137
- for (let i = 0; i < arr.length; i++) {
138
- const result = mapFn(arr[i]);
139
- if (result) return result;
136
+ export function mapFirstTruthy<T, R>( arr: T[], mapFn: TTransformer<T, R> ): R | null {
137
+ for ( let i = 0; i < arr.length; i++ ) {
138
+ const result = mapFn( arr[ i ] );
139
+ if ( result ) return result;
140
140
  }
141
141
  return null;
142
142
  }
143
143
 
144
- export function makeArrayEmpty( arr: unknown[] ): void {
145
- arr.splice( 0, arr.length );
144
+ export function listToDict<T, K extends string, V>( arr: T[], mapFn: TTransformer<T, [ K, V ]> ): Record<K, V> {
145
+ return arr.reduce( ( dict: Partial<Record<K, V>>, cur: T ) => {
146
+ const [ key, value ] = mapFn( cur );
147
+ return { ...dict, [ key ]: value };
148
+ }, {} satisfies Partial<Record<K, V>> );
149
+ }
150
+
151
+ export function countArrayBy<T, K extends string>( arr: T[], mapFn: TTransformer<T, K> ): Partial<Record<K, number>> {
152
+ return arr.reduce( ( dict: Partial<Record<K, number>>, cur: T ) => {
153
+ const value = mapFn( cur );
154
+ const count = ( dict[ value ] ?? 0 ) + 1;
155
+ return { ...dict, [ value ]: count };
156
+ }, {} satisfies Partial<Record<K, number>> );
157
+ }
158
+
159
+ export function sumArrayBy<T>( arr: T[], mapFn: TTransformer<T, number> ): number {
160
+ return arr.reduce( ( sum: number, cur: T ) => {
161
+ const value = mapFn( cur );
162
+ return sum + value;
163
+ }, 0 );
146
164
  }