### Install typescript-functional-extensions via npm Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/README.md Install the library using npm. This is the primary method for adding the package to your project. ```bash npm i typescript-functional-extensions ``` -------------------------------- ### Safely Get First Element with tryFirst (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Demonstrates using `Maybe.tryFirst()` to safely retrieve the first element from an array. If the array is empty, it results in a 'none' Maybe. The example shows successful retrieval of the first element. ```typescript const maybe = Maybe.tryFirst(['apple', 'banana']); console.log(maybe.getValueOrThrow()); // 'apple' ``` -------------------------------- ### Create and Use Maybe with No Value (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Illustrates creating an empty 'Maybe' instance using `Maybe.none()`. This shows how to check for the absence of a value and retrieve a default value, or how attempting to get the value directly will throw an error. ```typescript const maybe = Maybe.none(); console.log(maybe.hasValue); // false console.log(maybe.hasNoValue); // true console.log(maybe.getValueOrDefault('banana')); // 'banana' console.log(maybe.getValueOrThrow()); // throws Error 'No value' ``` -------------------------------- ### Safely Get First Element with Predicate (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Illustrates using `Maybe.tryFirst()` with a predicate function to find the first element in an array that satisfies a condition. If no element matches, it returns a 'none' Maybe. ```typescript const maybe = Maybe.tryFirst(['apple', 'banana'], (fruit) => fruit.length > 6); console.log(maybe.getValueOrThrow()); // throws Error 'No value' ``` -------------------------------- ### Safely Get Last Element with tryLast (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Shows how to use `Maybe.tryLast()` to safely retrieve the last element from an array that matches a given predicate. If no element satisfies the condition, it results in a 'none' Maybe. ```typescript const maybe = Maybe.tryLast( ['apple', 'banana', 'mango'], (fruit) => fruit.length === 5 ); console.log(maybe.getValueOrThrow()); // 'mango' ``` -------------------------------- ### Safely Execute Potentially Throwing Operations with Result.try in TypeScript Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Explains how to use Result.try to wrap functions that might throw exceptions. It converts caught errors into Result failures, allowing for consistent error handling. Includes examples of custom error message formatting and handling custom error types. ```typescript import { Result } from 'typescript-functional-extensions'; // Wrap potentially throwing function function parseJSON(json: string): Result { return Result.try( () => JSON.parse(json) as T, (error) => `Parse error: ${(error as Error).message}` ); } const validResult = parseJSON<{ name: string }>('{"name": "Alice"}'); console.log(validResult.isSuccess); // true console.log(validResult.getValueOrThrow()); // { name: 'Alice' } const invalidResult = parseJSON('invalid json'); console.log(invalidResult.isFailure); // true console.log(invalidResult.getErrorOrThrow()); // 'Parse error: Unexpected token...' // With custom error types type AppError = { code: string; message: string }; const result = Result.try( () => { throw new Error('Connection failed'); }, (error) => ({ code: 'CONN_ERR', message: (error as Error).message, }) ); console.log(result.getErrorOrThrow()); // { code: 'CONN_ERR', message: 'Connection failed' } ``` -------------------------------- ### Safely Get Last Element with No Match (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Demonstrates `Maybe.tryLast()` when no element in the array satisfies the provided predicate. This scenario correctly results in a 'none' Maybe, preventing errors. ```typescript const maybe = Maybe.tryLast( ['apple', 'banana', 'mango'], (fruit) => fruit === 'pear' ); console.log(maybe.getValueOrThrow()); // throws Error 'No value' ``` -------------------------------- ### Initialize Maybe instances Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Demonstrates creating Maybe instances using some, none, and from factory methods. These methods handle defined values, empty states, and automatic conversion from potentially null or undefined inputs. ```typescript import { Maybe } from 'typescript-functional-extensions'; // Create a Maybe with a value const some = Maybe.some('apple'); console.log(some.hasValue); // true console.log(some.hasNoValue); // false console.log(some.getValueOrThrow()); // 'apple' console.log(some.getValueOrDefault('banana')); // 'apple' // Create a Maybe with no value const none = Maybe.none(); console.log(none.hasValue); // false console.log(none.hasNoValue); // true console.log(none.getValueOrDefault('banana')); // 'banana' // Create from potentially undefined value const fromUndefined = Maybe.from(undefined); console.log(fromUndefined.hasNoValue); // true const fromValue = Maybe.from('cherry'); console.log(fromValue.getValueOrThrow()); // 'cherry' ``` -------------------------------- ### Initialize MaybeAsync instances Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Shows how to create MaybeAsync instances from raw values, Promises, or existing Maybe objects. All operations are asynchronous and return Promises. ```typescript import { Maybe, MaybeAsync } from 'typescript-functional-extensions'; // Create from value const some = MaybeAsync.some('apple'); console.log(await some.hasValue); // true console.log(await some.getValueOrThrow()); // 'apple' // Create empty const none = MaybeAsync.none(); console.log(await none.hasNoValue); // true console.log(await none.getValueOrDefault('default')); // 'default' // Create from Maybe const fromMaybe = MaybeAsync.from(Maybe.some('banana')); console.log(await fromMaybe.getValueOrThrow()); // 'banana' // Create from Promise const fromPromise = MaybeAsync.from(Promise.resolve('cherry')); console.log(await fromPromise.getValueOrThrow()); // 'cherry' // Create from Promise const fromMaybePromise = MaybeAsync.from( Promise.resolve(Maybe.some('date')) ); console.log(await fromMaybePromise.getValueOrThrow()); // 'date' // Undefined in Promise becomes none const fromUndefined = MaybeAsync.from( Promise.resolve(undefined) ); console.log(await fromUndefined.hasNoValue); // true ``` -------------------------------- ### Import Fetch Utilities in TypeScript Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/README.md Demonstrates importing utility functions for handling fetch requests and responses, specifically 'fetchResponse' and 'fetchJsonResponse'. These utilities streamline asynchronous data fetching operations. ```typescript import { fetchResponse, fetchJsonResponse, } from 'typescript-functional-extensions'; ``` -------------------------------- ### Initialize MaybeAsync with Some or None Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybeAsync.md Demonstrates how to instantiate a MaybeAsync object representing a present value (Some) or an empty value (None). It showcases methods for checking existence and retrieving values with fallbacks. ```typescript const maybe = MaybeAsync.some('apple'); console.log(await maybe.hasValue); // true console.log(await maybe.hasNoValue); // false console.log(await maybe.getValueOrDefault('banana')); // 'apple' console.log(await maybe.getValueOrThrow()); // 'apple' const maybeNone = MaybeAsync.none(); console.log(await maybeNone.hasValue); // false console.log(await maybeNone.hasNoValue); // true console.log(await maybeNone.getValueOrDefault('banana')); // 'banana' console.log(await maybeNone.getValueOrThrow()); // throws Error 'No value' ``` -------------------------------- ### Create ResultAsync Instances Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Demonstrates creating ResultAsync objects from direct values, existing Result instances, Promises, or Promise-wrapped Results. ```typescript import { Result, ResultAsync } from 'typescript-functional-extensions'; // Create successful ResultAsync const success = ResultAsync.success('operation completed'); console.log(await success.isSuccess); // true console.log(await success.getValueOrThrow()); // 'operation completed' // Create failed ResultAsync const failure = ResultAsync.failure('operation failed'); console.log(await failure.isFailure); // true console.log(await failure.getErrorOrThrow()); // 'operation failed' // Create from Result const fromResult = ResultAsync.from(Result.success(42)); console.log(await fromResult.getValueOrThrow()); // 42 // Create from Promise const fromPromiseResult = ResultAsync.from( Promise.resolve(Result.success('async data')) ); console.log(await fromPromiseResult.getValueOrThrow()); // 'async data' // Create from Promise (auto-wraps in success) const fromPromise = ResultAsync.from( Promise.resolve('raw value') ); console.log(await fromPromise.getValueOrThrow()); // 'raw value' ``` -------------------------------- ### Import Maybe monad from Unpkg ES Modules Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/README.md Demonstrates how to import and use the Maybe monad from the library's ES Modules distribution hosted on Unpkg. This is useful for direct browser usage or environments supporting ES Modules. ```javascript const { Maybe } = await import( 'https://unpkg.com/typescript-functional-extensions@3.0.0/dist/esm/maybe.js' ); const maybe = Maybe.some('test'); ``` -------------------------------- ### Create Success/Failure ResultAsync Instances Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/resultAsync.md Demonstrates how to create ResultAsync instances representing either a successful outcome with a value or a failed outcome with an error. It shows how to retrieve the value or error using specific methods. ```typescript const successfulResult = ResultAsync.success('apple'); console.log(await successfulResult.getValueOrThrow()); // 'apple' const failedResult = ResultAsync.failure('no fruit'); console.log(await failedResult.getErrorOrThrow()); // 'no fruit' ``` -------------------------------- ### Import Utility Functions in TypeScript Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/README.md Demonstrates importing various utility functions such as 'never', 'isDefined', 'isSome', 'isNone', 'isFunction', 'isPromise', and 'noop'. These utilities help in common programming tasks and checks. ```typescript import { never, isDefined, isSome, isNone, isFunction, isPromise, noop, } from 'typescript-functional-extensions'; ``` -------------------------------- ### Create and Use Maybe with Some Value (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Demonstrates creating a 'Maybe' instance with a value using `Maybe.some()`. It shows how to check for the presence of a value, retrieve it, and handle cases where a default value might be needed. ```typescript const maybe = Maybe.some('apple'); console.log(maybe.hasValue); // true console.log(maybe.hasNoValue); // false console.log(maybe.getValueOrDefault('banana')); // 'apple' console.log(maybe.getValueOrThrow()); // 'apple' ``` -------------------------------- ### Import Value Conversion Utilities in TypeScript Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/README.md Shows how to import utility functions for converting specific values (like zero, empty strings) into the 'None' state of the Maybe monad. This simplifies handling default or empty states. ```typescript import { zeroAsNone, emptyStringAsNone, emptyOrWhiteSpaceStringAsNone, } from 'typescript-functional-extensions'; ``` -------------------------------- ### Chain Async Transformations with ResultAsync.map and ResultAsync.bind Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Demonstrates chaining asynchronous operations using ResultAsync.map for transformations and ResultAsync.bind for operations that return another ResultAsync. This allows for sequential execution and error propagation in async workflows. ```typescript import { Result, ResultAsync } from 'typescript-functional-extensions'; type User = { id: number; name: string; email: string }; async function fetchUser(id: number): Promise { return { id, name: 'Alice', email: 'alice@example.com' }; } async function fetchPermissions(userId: number): Promise { return ['read', 'write']; } // Chain async operations with map const userName = ResultAsync.try(() => fetchUser(1), String) .map((user) => user.name) .map((name) => name.toUpperCase()); console.log(await userName.getValueOrThrow()); // 'ALICE' // Chain with bind for ResultAsync-returning operations const userWithPermissions = ResultAsync.try(() => fetchUser(1), String) .bind((user) => ResultAsync.try(() => fetchPermissions(user.id), String) .map((perms) => ({ ...user, permissions: perms })) ); console.log(await userWithPermissions.getValueOrThrow()); // { id: 1, name: 'Alice', email: 'alice@example.com', permissions: ['read', 'write'] } ``` -------------------------------- ### Create Success/Failure Results in TypeScript Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Demonstrates how to create Result objects representing successful operations with a value or failed operations with an error. It shows how to check the status (isSuccess, isFailure), retrieve values or errors, and use type guards for safer access. Supports creating results with or without a value (Unit). ```typescript import { Result } from 'typescript-functional-extensions'; // Create successful result const success = Result.success('operation completed'); console.log(success.isSuccess); // true console.log(success.isFailure); // false console.log(success.getValueOrThrow()); // 'operation completed' // Create failed result const failure = Result.failure('something went wrong'); console.log(failure.isSuccess); // false console.log(failure.isFailure); // true console.log(failure.getErrorOrThrow()); // 'something went wrong' // Create success with no value (Unit) const unitSuccess = Result.success(); console.log(unitSuccess.isSuccess); // true // Use type guards const result = Result.success(42); if (result.hasValue()) { console.log(result.value); // TypeScript knows value exists } if (result.hasError()) { console.log(result.error); // TypeScript knows error exists } ``` -------------------------------- ### Handle Some and None Cases with match (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Demonstrates the `match` function, which allows for handling both the 'some' and 'none' states of a 'Maybe' instance. It executes a specific function based on whether a value is present. ```typescript const maybe = Maybe.some({ type: 'fruit', name: 'apple' }) .map(({ type }) => ({ type, name: 'banana' })) .map((food) => food.name) .map((name) => name.length) .match({ some: (number) => console.log(number), none: () => console.log('None!'), }); // 6 ``` -------------------------------- ### Import Core Monads in TypeScript Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/README.md Shows how to import the core monads (Maybe, MaybeAsync, Result, ResultAsync) from the typescript-functional-extensions library. These are fundamental types for functional programming patterns. ```typescript import { Maybe, MaybeAsync, Result, ResultAsync, } from 'typescript-functional-extensions'; ``` -------------------------------- ### Recover from Result failures using compensate Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Demonstrates how to chain multiple Result-returning functions to handle errors gracefully. It supports sequential recovery attempts and error transformation. ```typescript import { Result } from 'typescript-functional-extensions'; type Config = { apiUrl: string }; function loadFromEnvironment(): Result { return Result.failure('Environment not configured'); } function loadFromFile(): Result { return Result.failure('Config file not found'); } function useDefaults(): Result { return Result.success({ apiUrl: 'http://localhost:3000' }); } // Try multiple sources in order const config = loadFromEnvironment() .compensate(loadFromFile) .compensate(useDefaults); console.log(config.getValueOrThrow()); // { apiUrl: 'http://localhost:3000' } // Recovery with error transformation const recovered = Result.failure('original error') .compensate((error) => { console.log(`Recovering from: ${error}`); return Result.success(0); // Default value }); console.log(recovered.getValueOrThrow()); // 0 ``` -------------------------------- ### Create MaybeAsync from various sources Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybeAsync.md Illustrates the flexibility of the MaybeAsync.from factory method, which accepts synchronous Maybe instances, Promises, or raw values to wrap them into an asynchronous optional context. ```typescript const maybeFromMaybe = MaybeAsync.from(Maybe.from('apple')); const promise = Promise.resolve(Maybe.from('apple')); const maybeFromPromise = MaybeAsync.from(promise); const promiseValue = Promise.resolve('apple'); const maybeFromValue = MaybeAsync.from(promiseValue); const promiseUndefined = Promise.resolve(undefined); const maybeFromUndefined = MaybeAsync.from(promiseUndefined); ``` -------------------------------- ### Retrieve array elements safely with Maybe Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Uses tryFirst and tryLast to extract elements from arrays safely. These methods return a Maybe instance, avoiding undefined errors when accessing empty arrays or non-existent items. ```typescript import { Maybe } from 'typescript-functional-extensions'; const fruits = ['apple', 'banana', 'cherry', 'date']; // Get first element const first = Maybe.tryFirst(fruits); console.log(first.getValueOrThrow()); // 'apple' // Get first element matching predicate const firstLong = Maybe.tryFirst(fruits, (f) => f.length > 5); console.log(firstLong.getValueOrThrow()); // 'banana' // Get last element const last = Maybe.tryLast(fruits); console.log(last.getValueOrThrow()); // 'date' // Get last element matching predicate const lastFiveLetters = Maybe.tryLast(fruits, (f) => f.length === 5); console.log(lastFiveLetters.getValueOrThrow()); // 'apple' ``` -------------------------------- ### Implement Async Recovery with ResultAsync.compensate Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Demonstrates how to use ResultAsync.compensate to provide a fallback mechanism when an asynchronous operation fails. It allows defining an alternative asynchronous operation to execute if the primary one results in an error, enabling graceful recovery. ```typescript import { Result, ResultAsync } from 'typescript-functional-extensions'; async function fetchFromPrimary(): Promise { throw new Error('Primary unavailable'); } async function fetchFromBackup(): Promise { return 'backup data'; } const withRecovery = ResultAsync.try(() => fetchFromPrimary(), String) .compensate((error) => { console.log(`Primary failed: ${error}, trying backup...`); return ResultAsync.try(() => fetchFromBackup(), String); }); console.log(await withRecovery.getValueOrThrow()); // 'backup data' ``` -------------------------------- ### Handle Optional Employee Data with Maybe in TypeScript Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/README.md Demonstrates using the Maybe type to safely access and process employee data, including handling cases where an employee or their manager might not exist. It chains operations like logging, providing fallbacks, and mapping values, finally matching on the presence or absence of data. ```typescript type Employee = { email: string; firstName: string; lastName: string; manager: Employee | undefined; }; function yourBusinessProcess(): Employee[] { // ... } const employees = yourBusinessProcess(); Maybe.tryFirst(employees) .tap(({ firstName, lastName, email }) => console.log(`Found Employee: ${firstName} ${lastName}, ${email}`)) .bind(employee => Maybe.from(employee.manager) .or({ email: 'supervisor@business.com', firstName: 'Company', lastName: 'Supervisor', manager: undefined }) .map(manager => ({ manager, employee })) ) .match({ some(attendees => scheduleMeeting(attendees.manager, attendees.employee)), none(() => console.log(`The business process did not return any employees`)) }); ``` -------------------------------- ### Pattern Matching with Maybe.match Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt The match method performs exhaustive pattern matching on a Maybe, allowing for different logic paths based on whether the value exists. It is ideal for conditional UI rendering or branching logic. ```typescript import { Maybe } from 'typescript-functional-extensions'; const user = Maybe.some({ name: 'Alice', age: 30 }); const greeting = user.match({ some: (u) => `Hello, ${u.name}!`, none: () => 'Hello, guest!', }); ``` -------------------------------- ### Handle Success and Failure Results in TypeScript Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/result.md Demonstrates how to instantiate successful and failed results using the Result class. It shows how to retrieve values or errors using the getValueOrThrow and getErrorOrThrow methods. ```typescript const successfulResult = Result.success('apple'); console.log(successfulResult.getValueOrThrow()); // 'apple' const failedResult = Result.failure('no fruit'); console.log(failedResult.getErrorOrThrow()); // 'no fruit' ``` -------------------------------- ### Fetch Raw Responses with ResultAsync using fetchResponse Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Provides a utility function, fetchResponse, to wrap fetch API calls into a ResultAsync, specifically for handling raw responses like files. It includes error handling for network issues and non-OK HTTP status codes. ```typescript import { fetchJsonResponse, fetchResponse } from 'typescript-functional-extensions'; // Fetch raw response const responseResult = fetchResponse( fetch('https://api.example.com/files/doc.pdf'), (error) => `Download failed: ${error}` ); await responseResult.tap(async (response) => { const blob = await response.blob(); console.log(`Downloaded ${blob.size} bytes`); }); ``` -------------------------------- ### Match Operation on None Maybe (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Shows how the `match` function handles a 'none' Maybe instance. The 'none' case function is executed, providing a way to gracefully manage the absence of a value. ```typescript type Food = { type: string; name: string; }; const maybe = Maybe.none() .map(({ type }) => ({ type, name: 'banana' })) .map((food) => food.name) .map((name) => name.length) .match({ some: (number) => console.log(number), none: () => console.log('None!'), }); // None! ``` -------------------------------- ### Custom Pipe Operator for Maybe and Result in TypeScript Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Demonstrates creating and using custom operator functions with the pipe operator for composing transformations on Maybe and Result types. This allows for building reusable pipelines for data manipulation and validation. ```typescript import { Maybe, MaybeOpFn, Result, ResultOpFn } from 'typescript-functional-extensions'; // Custom Maybe operator function logValue(label: string): MaybeOpFn { return (maybe) => { if (maybe.hasValue) { console.log(`${label}: ${maybe.getValueOrThrow()}`); } else { console.log(`${label}: (no value)`); } return maybe; }; } function validateLength(min: number): MaybeOpFn { return (maybe) => { if (maybe.hasNoValue) return maybe; const value = maybe.getValueOrThrow(); return value.length >= min ? maybe : Maybe.none(); }; } // Use custom operators in pipe const result = Maybe.some('Hello World') .pipe( logValue('Input'), validateLength(5), logValue('After validation') ) .map((s) => s.toUpperCase()); console.log(result.getValueOrThrow()); // 'HELLO WORLD' // Custom Result operator function addTimestamp(): ResultOpFn { return (result) => { return result.map((value) => ({ ...value, timestamp: new Date(), })); }; } const dataWithTimestamp = Result.success({ name: 'Alice' }) .pipe(addTimestamp()); console.log(dataWithTimestamp.getValueOrThrow()); // { name: 'Alice', timestamp: 2024-... } ``` -------------------------------- ### Create Maybe from Undefined Value (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Shows how to create a 'Maybe' instance from a potentially undefined value using `Maybe.from()`. This is useful for safely handling variables that might not have a value, resulting in a 'none' Maybe. ```typescript const maybe = Maybe.from(undefined); console.log(maybe.hasValue); // false console.log(maybe.hasNoValue); // true console.log(maybe.getValueOrDefault('banana')); // 'banana' console.log(maybe.getValueOrThrow()); // throws Error 'No value' ``` -------------------------------- ### Maybe Utility Functions in TypeScript Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Helper functions to convert empty strings or zero values into Maybe instances, simplifying checks for null, undefined, empty strings, or zero. These functions are part of the 'typescript-functional-extensions' library. ```typescript import { emptyStringAsNone, emptyOrWhiteSpaceStringAsNone, zeroAsNone, } from 'typescript-functional-extensions'; // Empty string becomes none console.log(emptyStringAsNone('hello').getValueOrThrow()); // 'hello' console.log(emptyStringAsNone('').hasNoValue); // true console.log(emptyStringAsNone(null).hasNoValue); // true // Whitespace-only strings become none console.log(emptyOrWhiteSpaceStringAsNone('hello').hasValue); // true console.log(emptyOrWhiteSpaceStringAsNone(' ').hasNoValue); // true console.log(emptyOrWhiteSpaceStringAsNone('').hasNoValue); // true // Zero becomes none console.log(zeroAsNone(42).getValueOrThrow()); // 42 console.log(zeroAsNone(0).hasNoValue); // true console.log(zeroAsNone(null).hasNoValue); // true // Practical example: Form input processing function processFormField(input: string | undefined): string { return emptyOrWhiteSpaceStringAsNone(input) .map((s) => s.trim()) .getValueOrDefault('(not provided)'); } console.log(processFormField(' Alice ')); // 'Alice' console.log(processFormField(' ')); // '(not provided)' console.log(processFormField(undefined)); // '(not provided)' ``` -------------------------------- ### Combine Multiple Results into One in TypeScript Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Illustrates how to use Result.combine to aggregate multiple Result objects into a single Result. If all input Results are successful, the output Result contains an object with all their values. If any input Result is a failure, the output Result is a failure containing all errors. ```typescript import { Result } from 'typescript-functional-extensions'; // All successful - returns combined values const combined = Result.combine({ name: Result.success('Alice'), age: Result.success(30), email: Result.success('alice@example.com'), }); console.log(combined.isSuccess); // true console.log(combined.getValueOrThrow()); // { name: 'Alice', age: 30, email: 'alice@example.com' } // One failure - entire result fails const withFailure = Result.combine({ name: Result.success('Bob'), age: Result.failure('Age is required'), email: Result.failure('Email is invalid'), }); console.log(withFailure.isFailure); // true console.log(withFailure.getErrorOrThrow()); // 'Age is required, Email is invalid' // Practical example: Form validation function validateForm(data: { name?: string; email?: string }) { return Result.combine({ name: data.name ? Result.success(data.name) : Result.failure('Name is required'), email: data.email?.includes('@') ? Result.success(data.email) : Result.failure('Valid email is required'), }); } const valid = validateForm({ name: 'Alice', email: 'alice@test.com' }); console.log(valid.getValueOrThrow()); // { name: 'Alice', email: 'alice@test.com' } ``` -------------------------------- ### Converting Maybe to Result with Maybe.toResult Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Converts a Maybe instance into a Result type, mapping the absence of a value to a failure state with a specified error message. This is useful for integrating optional values into error-handling workflows. ```typescript import { Maybe } from 'typescript-functional-extensions'; const success = Maybe.some('data').toResult('No data found'); const failure = Maybe.none().toResult('No data found'); ``` -------------------------------- ### Fetch JSON Responses with ResultAsync using fetchJsonResponse Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Wraps the native fetch API to return a ResultAsync, handling both network errors and non-OK HTTP responses. It allows for type-safe JSON parsing and custom error handling for API requests. ```typescript import { fetchJsonResponse, fetchResponse } from 'typescript-functional-extensions'; type User = { id: number; name: string }; type ApiError = { code: string; message: string }; // Fetch JSON with typed response const userResult = fetchJsonResponse( fetch('https://api.example.com/users/1'), (error) => `Request failed: ${error}` ); const user = await userResult.match({ success: (user) => `Found user: ${user.name}`, failure: (error) => `Error: ${error}`, }); // Fetch with custom error handling const customResult = fetchJsonResponse( fetch('https://api.example.com/users/1'), async (error) => { if (error instanceof Response) { const body = await error.json(); return { code: 'HTTP_ERROR', message: body.error }; } return { code: 'NETWORK_ERROR', message: String(error) }; } ); ``` -------------------------------- ### Convert Result to ResultAsync Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/resultAsync.md Illustrates the conversion of a synchronous Result object into an asynchronous ResultAsync object. This is useful when integrating existing Result-based logic into an asynchronous workflow. ```typescript const result = Result.success('apple'); const resultAsync = ResultAsync.from(result); console.log(await resultAsync.getValueOrThrow()); // 'apple' ``` ```typescript const result = Result.failure('no fruit'); const resultAsync = ResultAsync.from(Promise.resolve(result)); console.log(await resultAsync.getErrorOrThrow()); // 'no fruit' ``` -------------------------------- ### Handle Async Side Effects with ResultAsync.tap and ResultAsync.tapFailure Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Illustrates using ResultAsync.tap to execute asynchronous side effects (like logging or saving) upon successful completion of an operation, and ResultAsync.tapFailure to handle side effects when an operation fails. This is useful for debugging and monitoring. ```typescript import { Result, ResultAsync } from 'typescript-functional-extensions'; async function saveToAuditLog(data: unknown) { console.log('Audit:', data); } // Async tap for logging/side effects const result = ResultAsync.success({ id: 1, name: 'Alice' }) .tap(async (user) => { console.log(`Processing user: ${user.name}`); await saveToAuditLog(user); }) .map((user) => user.name); async function notifyAdmin(error: string) { console.log('Admin notified of:', error); } // tapFailure for error logging const withErrorLogging = ResultAsync.failure('Connection failed') .tapFailure(async (error) => { console.error(`Error occurred: ${error}`); await notifyAdmin(error); }); ``` -------------------------------- ### Chaining Optional Operations with Maybe.bind Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt The bind method allows for chaining operations that return a Maybe, enabling safe navigation through nested optional properties. It stops execution if any step in the chain results in a none value. ```typescript import { Maybe } from 'typescript-functional-extensions'; type Employee = { name: string; manager: Employee | undefined; }; const employee: Employee = { name: 'Alice', manager: { name: 'Bob', manager: undefined, }, }; const managerName = Maybe.from(employee) .bind((e) => Maybe.from(e.manager)) .map((m) => m.name); console.log(managerName.getValueOrThrow()); // 'Bob' ``` -------------------------------- ### Combine Multiple Async Results Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Aggregates multiple ResultAsync instances into a single result. Use combine for parallel execution or combineInOrder for sequential execution. ```typescript import { Result, ResultAsync } from 'typescript-functional-extensions'; async function fetchUser(id: number) { return { id, name: 'Alice' }; } async function fetchOrders(userId: number) { return [{ id: 1, item: 'Book' }]; } async function fetchPreferences(userId: number) { return { theme: 'dark' }; } // Parallel execution const parallel = ResultAsync.combine({ user: ResultAsync.try(() => fetchUser(1), (e) => String(e)), orders: ResultAsync.try(() => fetchOrders(1), (e) => String(e)), prefs: ResultAsync.try(() => fetchPreferences(1), (e) => String(e)), }); const data = await parallel.getValueOrThrow(); console.log(data.user.name); // 'Alice' console.log(data.orders.length); // 1 console.log(data.prefs.theme); // 'dark' // Sequential execution (useful when order matters) const sequential = ResultAsync.combineInOrder({ step1: ResultAsync.success('first'), step2: ResultAsync.success('second'), step3: ResultAsync.success('third'), }); console.log(await sequential.getValueOrThrow()); // { step1: 'first', step2: 'second', step3: 'third' } // Mix Result and ResultAsync const mixed = ResultAsync.combine({ sync: Result.success('sync value'), async: ResultAsync.success('async value'), }); console.log(await mixed.getValueOrThrow()); // { sync: 'sync value', async: 'async value' } ``` -------------------------------- ### Providing Fallbacks with Maybe.or Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt The or method provides a mechanism to resolve a default value or a secondary Maybe when the primary instance contains no value. It supports static values, factory functions, and alternative Maybe instances. ```typescript import { Maybe } from 'typescript-functional-extensions'; const value1 = Maybe.none().or('default'); const value2 = Maybe.none().or(() => Math.random()); const value3 = Maybe.none().or(Maybe.some('backup')); ``` -------------------------------- ### Chaining Operations with Result.bind in TypeScript Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt The `bind` method chains Result-returning operations, enabling flat composition of operations that can fail. It takes a function that accepts the success value of the current Result and returns a new Result. If the current Result is a failure, `bind` short-circuits and returns that failure. This is crucial for sequential operations where any step might produce an error. ```typescript import { Result } from 'typescript-functional-extensions'; type User = { id: number; name: string }; type Order = { userId: number; items: string[] }; function getUser(id: number): Result { if (id <= 0) return Result.failure('Invalid user ID'); return Result.success({ id, name: 'Alice' }); } function getOrders(user: User): Result { if (user.id === 999) return Result.failure('User has no orders'); return Result.success([{ userId: user.id, items: ['item1', 'item2'] }]); } function calculateTotal(orders: Order[]): Result { if (orders.length === 0) return Result.failure('No orders to calculate'); return Result.success(orders.reduce((sum, o) => sum + o.items.length, 0)); } // Chain operations that may fail const result = getUser(1) .bind(getOrders) .bind(calculateTotal) .map((total) => `Total items: ${total}`); console.log(result.getValueOrThrow()); // 'Total items: 2' // Chain stops at first failure const failedResult = getUser(-1) .bind(getOrders) .bind(calculateTotal); console.log(failedResult.getErrorOrThrow()); // 'Invalid user ID' ``` -------------------------------- ### Executing Side Effects with Maybe.tap and Maybe.tapNone Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt These methods allow for executing side-effect functions based on the presence or absence of a value without altering the underlying Maybe instance. This is useful for logging or triggering external events during a functional chain. ```typescript import { Maybe } from 'typescript-functional-extensions'; const logFound = (value: string) => console.log(`Found: ${value}`); const logNotFound = () => console.log('Value not found'); Maybe.some('apple') .tap(logFound) .tapNone(logNotFound); Maybe.none() .tap(logFound) .tapNone(logNotFound); ``` -------------------------------- ### Apply Custom Operations with pipe (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Introduces the `pipe` function, which allows chaining custom operations (like logging) onto a 'Maybe' instance. This enables side effects or further transformations in a functional style. ```typescript // custom-operators.ts import { logger, LogLevel } from 'logger'; export function log( messageCreator: FunctionOfTtoK, logLevel: LogLevel = 'debug' ): MaybeOpFn { return (maybe) => { if (maybe.hasValue) { logger.log(messageCreator(maybe.getValueOrThrow()), logLevel); } else { logger.error('No value found!'); } return maybe; }; } // app.ts import { log } from './custom-operators.ts'; const maybe = Maybe.some('apple') .pipe(log((f) => `My fruit is ${f}`, 'information')) .map((f) => `${f} and banana`) .pipe(log((f) => `Now I have ${f}`)); ``` -------------------------------- ### Wrap Async Operations with ResultAsync.try Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Wraps asynchronous functions or Promises that may throw exceptions, converting caught errors into a failed Result using a provided error mapper. ```typescript import { ResultAsync } from 'typescript-functional-extensions'; // Wrap async function const result = ResultAsync.try( async () => { const response = await fetch('https://api.example.com/data'); return response.json(); }, (error) => `Fetch failed: ${(error as Error).message}` ); // Wrap Promise directly const promiseResult = ResultAsync.try( fetch('https://api.example.com/data').then((r) => r.json()), (error) => `Request failed: ${(error as Error).message}` ); // With async error handler const withAsyncErrorHandler = ResultAsync.try( async () => { throw new Error('Something went wrong'); }, async (error) => { // Can perform async cleanup or logging await logError(error); return `Logged error: ${(error as Error).message}`; } ); async function logError(error: unknown) { console.error('Error occurred:', error); } ``` -------------------------------- ### Asynchronous Optional Value Handling with MaybeAsync in TypeScript Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/README.md Introduces MaybeAsync for managing asynchronous operations that may or may not yield a value. It mirrors the functionality of Maybe but operates on Promises, allowing for declarative chaining of async steps and handling of potential null or undefined results in a non-blocking manner. ```typescript // MaybeAsync works like Maybe but for Promises. // Its methods accept Promises and its value-accessing methods return Promises. // Example usage would involve async functions and Promise-based operations. ``` -------------------------------- ### Pattern Matching and Final Processing with Result.match and Result.finally in TypeScript Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt The `match` method allows pattern matching on the Result's state, returning different values or executing different logic for success and failure cases. The `finally` method executes a given function regardless of the Result's state, typically used for cleanup or final processing, and it returns the original Result. ```typescript import { Result } from 'typescript-functional-extensions'; type ApiResponse = { data: T; status: number }; // match returns different values based on state function processResult(result: Result): ApiResponse { return result.match({ success: (value) => ({ data: value, status: 200 }), failure: (error) => ({ data: null, status: 400 }), }); } console.log(processResult(Result.success('hello'))); // { data: 'hello', status: 200 } console.log(processResult(Result.failure('error'))); // { data: null, status: 400 } // match for side effects Result.success('done').match({ success: (v) => console.log(`Completed: ${v}`), failure: (e) => console.error(`Failed: ${e}`), }); // finally executes regardless and receives the Result const logResult = Result.success(42).finally((result) => { console.log(`Result state: ${result.isSuccess ? 'success' : 'failure'}`); return result.isSuccess ? result.getValueOrThrow() : 0; }); console.log(logResult); // 42 ``` -------------------------------- ### Transform and chain MaybeAsync operations Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Utilizes map and bind to perform transformations on asynchronous optional values. Supports both synchronous and asynchronous projection functions. ```typescript import { Maybe, MaybeAsync } from 'typescript-functional-extensions'; // Async map with sync projection const mapped = MaybeAsync.some({ name: 'Alice', id: 1 }) .map((user) => user.name) .map((name) => name.toUpperCase()); console.log(await mapped.getValueOrThrow()); // 'ALICE' // Async map with async projection const asyncMapped = MaybeAsync.some(1) .map(async (n) => { await new Promise((r) => setTimeout(r, 100)); return n * 2; }); console.log(await asyncMapped.getValueOrThrow()); // 2 // bind with Maybe const bound = MaybeAsync.some({ managerId: 42 }) .bind((data) => Maybe.from(data.managerId > 0 ? data.managerId : undefined)); console.log(await bound.getValueOrThrow()); // 42 // bind with MaybeAsync async function fetchUser(id: number): Promise<{ name: string } | undefined> { if (id <= 0) return undefined; return { name: 'Bob' }; } const asyncBound = MaybeAsync.some(1) .bind((id) => MaybeAsync.from(fetchUser(id))) .map((user) => user.name); console.log(await asyncBound.getValueOrThrow()); // 'Bob' ``` -------------------------------- ### Convert MaybeAsync to ResultAsync Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Converts an asynchronous Maybe instance into a ResultAsync. If the Maybe is 'none', it results in a failure with the provided error message; otherwise, it succeeds with the value. ```typescript import { MaybeAsync } from 'typescript-functional-extensions'; // Convert some to success const success = MaybeAsync.some('data').toResult('Not found'); console.log(await success.isSuccess); // true console.log(await success.getValueOrThrow()); // 'data' // Convert none to failure const failure = MaybeAsync.none().toResult('Not found'); console.log(await failure.isFailure); // true console.log(await failure.getErrorOrThrow()); // 'Not found' // Practical async example async function findUser(id: number) { const user = id > 0 ? { id, name: 'Alice' } : undefined; return user; } const result = MaybeAsync.from(findUser(1)) .map((u) => u.name) .toResult('User not found'); console.log(await result.getValueOrThrow()); // 'Alice' ``` -------------------------------- ### Map Operation on None Maybe (TypeScript) Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/docs/maybe.md Illustrates the behavior of the `map` operation when called on a 'none' Maybe instance. Transformations are skipped, and the 'none' state is preserved, preventing errors. ```typescript type Food = { type: string; name: string; }; const maybe = Maybe.none() .map(({ type }) => ({ type, name: 'banana' })) .map((food) => food.name) .map((name) => name.length); console.log(maybe.getValueOrThrow()); // throws Error 'No value' ``` -------------------------------- ### Validate Async Operations with ResultAsync.ensure Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt Shows how to add validation steps to asynchronous operations using ResultAsync.ensure. This method allows you to check conditions on the successful result of an async operation and provide an error message if the condition is not met. ```typescript import { Result, ResultAsync } from 'typescript-functional-extensions'; type User = { id: number; name: string; email: string }; async function fetchUser(id: number): Promise { return { id, name: 'Alice', email: 'alice@example.com' }; } // Validate with ensure const validated = ResultAsync.try(() => fetchUser(1), String) .ensure( (user) => user.email.includes('@'), (user) => `Invalid email for user ${user.name}` ) .ensure( (user) => user.name.length > 0, 'Name cannot be empty' ); console.log(await validated.isSuccess); // true ``` -------------------------------- ### Handle Operations with Result in TypeScript Source: https://github.com/seangwright/typescript-functional-extensions/blob/main/README.md The Result type allows for declarative definition of processes without explicit try/catch blocks. It chains operations, handling success and failure states through methods like try, ensure, bind, map, and match. Errors are converted to failed Result instances, and successful operations return a Result with the computed value. Dependencies include the Result type itself and potentially other types like Maybe. ```typescript type Employee = { id: number; email: string; firstName: string; lastName: string; managerId: number | undefined; }; function getEmployee(employeeId): Employee | undefined { const employee = getEmployee(employeeId); if (!employee) { throw Error(`Could not find employee ${employeeId}!`); } return employee; } Result.try( () => getEmployee(42), (error) => `Retrieving the employee failed: ${error}` ) .ensure( (employee) => employee.email.endsWith('@business.com'), ({ firstName, lastName }) => `Employee ${firstName} ${lastName} is a contractor and not a full employee` ) .bind(({ firstName, lastName, managerId }) => Maybe.from(managerId).toResult( `Employee ${firstName} ${lastName} does not have a manager` ) ) .map((managerId) => ({ managerId, employeeFullName: `${firstName} ${lastName}`, })) .bind(({ managerId, employeeFullName }) => Result.try( () => getEmployee(managerId), (error) => `Retrieving the manager failed: ${error}` ).map((manager) => ({ manager, employeeFullName })) ) .match({ success: ({ manager: { email }, employeeFullName }) => sendReminder(email, `Remember to say hello to ${employeeFullName}`), failure: (error) => sendSupervisorAlert(error), }); ``` -------------------------------- ### Executing Side Effects with Result.tap, tapFailure, tapEither in TypeScript Source: https://context7.com/seangwright/typescript-functional-extensions/llms.txt The `tap`, `tapFailure`, and `tapEither` methods execute side effects based on the Result's state without altering the Result itself. `tap` runs for success, `tapFailure` for failure, and `tapEither` runs regardless of the state. `tapIf` allows conditional execution of side effects based on a predicate. ```typescript import { Result } from 'typescript-functional-extensions'; // tap executes for success Result.success('data') .tap((value) => console.log(`Success: ${value}`)) .tapFailure((error) => console.log(`Error: ${error}`)); // Logs: "Success: data" // tapFailure executes for failure Result.failure('something went wrong') .tap((value) => console.log(`Success: ${value}`)) .tapFailure((error) => console.log(`Error: ${error}`)); // Logs: "Error: something went wrong" // tapEither executes regardless of state Result.success('data') .tapEither(() => console.log('Operation completed')); // Logs: "Operation completed" // Conditional tap with tapIf Result.success(100) .tapIf( (n) => n > 50, (n) => console.log(`Large value: ${n}`) ) .tapIf( (n) => n < 10, (n) => console.log(`Small value: ${n}`) ); // Logs: "Large value: 100" ```