@@ -116,6 +116,10 @@ const parts = split("-", "hello-world-js"); // ["hello", "world", "js"]
116116// Split string by line breaks (handles both \n and \r\n)
117117const lines = splitByLineBreak (" line1\n line2\r\n line3" );
118118console .log (lines ); // ["line1", "line2", "line3"]
119+
120+ // Parse boolean value with custom default
121+ const isEnabled = parseValueToBoolean (" yes" , false ); // true
122+ const debugMode = parseValueToBoolean (" invalid" , " auto" ); // "auto"
119123```
120124
121125#### Promise Utilities
@@ -307,44 +311,52 @@ const pattern = convertPathToPattern("/home/user/project");
307311### Result Pattern - Functional Error Handling
308312
309313``` typescript
310- import { err , ok , Result , safeTry } from " @goodbyenjn/utils/result" ;
314+ import { err , ok , Result } from " @goodbyenjn/utils/result" ;
311315
312316// Create results explicitly
313317const success = ok (42 );
314318const failure = err (" Something went wrong" );
315319
316320// Handle results with chainable methods
317321const doubled = success
318- .map (value => value * 2 )
322+ .map (value => value * 2 ) // Supports async: .map(async v => v * 2) returns Promise<Result>
319323 .mapErr (err => ` Error: ${err } ` )
320324 .unwrapOr (0 ); // 84
321325
322326// Transform error type
323327const result: Result <string , Error > = ok (" value" );
324328const transformed = result .mapErr (() => new Error (" Custom error" ));
325329
326- // Convert throwing functions to Result
330+ // Convert throwing functions or promises to Result
327331async function fetchUser(id : string ) {
328- // If the function throws, it's caught and wrapped in Err
329- const user = await Result .fromCallable (() => JSON .parse (userJson ));
332+ // Result.try catches thrown errors
333+ const user = await Result .try (() => JSON .parse (userJson ));
334+ // Or handle promise rejections
335+ const user = await Result .try (fetch (` /api/users/${id } ` ));
330336
331337 return user .map (u => u .name ).mapErr (err => new Error (` Failed to parse user: ${err .message } ` ));
332338}
333339
340+ // Wrap a function to always return a Result
341+ const safeParse = Result .wrap (JSON .parse , Error );
342+ const data = safeParse (' {"valid": true}' ); // Result<any, Error>
343+
334344// Combine multiple Results
335345const results = [ok (1 ), ok (2 ), err (" oops" ), ok (4 )];
336346const combined = Result .all (... results ); // Err("oops")
337347
338- // Safe try-catch alternative
339- const safeTryExample = await safeTry (async () => {
340- return await fetch (" /api/data" ).then (r => r .json ());
348+ // Generator-based "do" notation for flattening Results
349+ const finalResult = Result .gen (function * () {
350+ const a = yield * ok (10 );
351+ const b = yield * ok (20 );
352+ return a + b ;
353+ }); // ok(30)
354+
355+ // Supports async generators
356+ const asyncFinal = await Result .gen (async function * () {
357+ const user = yield * await fetchUser (" 1" );
358+ return user .name ;
341359});
342-
343- if (safeTryExample .isOk ()) {
344- console .log (" Data:" , safeTryExample .unwrap ());
345- } else {
346- console .error (" Failed:" , safeTryExample .unwrapErr ());
347- }
348360```
349361
350362### Type Utilities
@@ -356,46 +368,56 @@ import type {
356368 YieldType ,
357369 OmitByKey ,
358370 SetNullable ,
371+ TemplateFn ,
359372} from " @goodbyenjn/utils/types" ;
360373
374+ // ... (other types)
375+
376+ // Template string function type
377+ const myTag: TemplateFn <string > = (strings , ... values ) => {
378+ return strings [0 ] + values [0 ];
379+ };
380+ ```
381+
361382// Nullable type for values that can be null or undefined
362383type User = {
363- id: string ;
364- name: string ;
365- email: Nullable <string >; // string | null | undefined
384+ id: string;
385+ name: string;
386+ email: Nullable<string >; // string | null | undefined
366387};
367388
368389// Optional type (undefined but not null)
369390type Profile = {
370- bio: Optional <string >; // string | undefined
391+ bio: Optional<string >; // string | undefined
371392};
372393
373394// Extract yield type from generators
374- function * numberGenerator() {
375- yield 1 ;
376- yield 2 ;
377- yield 3 ;
395+ function\ * numberGenerator() {
396+ yield 1;
397+ yield 2;
398+ yield 3;
378399}
379400
380401type NumberType = YieldType<typeof numberGenerator >; // number
381402
382403// Omit properties by their value type
383404type Config = {
384- name: string ;
385- debug: boolean ;
386- verbose: boolean ;
387- timeout: number ;
405+ name: string;
406+ debug: boolean;
407+ verbose: boolean;
408+ timeout: number;
388409};
389410type WithoutBooleans = OmitByKey<Config, boolean>; // { name: string; timeout: number }
390411
391412// Set specific properties to nullable
392413type APIResponse = {
393- id: number ;
394- name: string ;
395- email: string ;
414+ id: number;
415+ name: string;
416+ email: string;
396417};
397418type PartialResponse = SetNullable<APIResponse, "email" | "name">; // email and name become nullable
398- ```
419+
420+ ````
399421
400422### Extended Remeda Utilities
401423
@@ -492,7 +514,7 @@ const totalAge = sumBy(
492514// Chunk array into groups
493515const chunked = chunk(users, 2);
494516// [[user1, user2], [user3]]
495- ```
517+ ````
496518
497519## API Reference
498520
0 commit comments