ts-data-forge
Version:
[](https://www.npmjs.com/package/ts-data-forge) [](https://www.npmjs.com/package/ts-data-forge) [ : false;
/**
* Type-safe pattern matching function for string-based discriminated unions.
*
* Provides compile-time guarantees for exhaustive case handling when working with
* literal string unions. Automatically enforces completeness checking when all
* cases are covered, and requires a default value when cases are incomplete.
*
* ## Key Features:
* - **Exhaustive Matching**: When all cases of a literal union are handled, no default value is needed
* - **Partial Matching**: When cases are incomplete or working with general string types, a default value is required
* - **Type Safety**: Prevents extra cases and ensures only valid keys are used
* - **Strict Property Checking**: Rejects objects with unexpected properties
*
* @param target - The value to match against
* @param cases - Object mapping possible values to their corresponding results
* @param defaultValue - Fallback value (required when not all cases are covered)
* @returns The matched result or default value
*
* @example
* Exhaustive matching (no default needed):
* ```typescript
* type Status = 'loading' | 'success' | 'error';
* const status: Status = 'loading';
*
* const message = match(status, {
* loading: 'Please wait...',
* success: 'Operation completed!',
* error: 'Something went wrong'
* });
* // Type: string
* // Result: 'Please wait...'
* ```
*
* @example
* Partial matching (default required):
* ```typescript
* type Priority = 'low' | 'medium' | 'high' | 'critical';
* const priority: Priority = 'medium';
*
* const color = match(priority, {
* high: 'red',
* critical: 'darkred'
* }, 'gray'); // Default required for uncovered cases
* // Type: 'red' | 'darkred' | 'gray'
* // Result: 'gray'
* ```
*
* @example
* Working with general string types:
* ```typescript
* const userInput: string = getUserInput();
*
* const route = match(userInput, {
* 'home': '/',
* 'about': '/about',
* 'contact': '/contact'
* }, '/404'); // Default required for string type
* // Type: '/' | '/about' | '/contact' | '/404'
* ```
*
* @example
* HTTP status code handling:
* ```typescript
* type HttpStatus = 200 | 404 | 500;
* const status: HttpStatus = 404;
*
* const response = match(String(status), {
* '200': { ok: true, message: 'Success' },
* '404': { ok: false, message: 'Not Found' },
* '500': { ok: false, message: 'Server Error' }
* });
* // All cases covered, no default needed
* // Result: { ok: false, message: 'Not Found' }
* ```
*
* @example
* Complex discriminated union handling:
* ```typescript
* type ApiResponse =
* | { status: 'loading' }
* | { status: 'success'; data: string }
* | { status: 'error'; error: string };
*
* const handleResponse = (response: ApiResponse) =>
* match(response.status, {
* loading: 'Please wait...',
* success: 'Data loaded successfully!',
* error: 'Failed to load data'
* });
* ```
*
* @example
* Advanced usage with functional composition:
* ```typescript
* // Creating reusable matchers
* const logLevelToColor = (level: string) => match(level, {
* 'debug': 'gray',
* 'info': 'blue',
* 'warn': 'yellow',
* 'error': 'red'
* }, 'black'); // Default for unknown levels
*
* const logLevelToIcon = (level: string) => match(level, {
* 'debug': 'đ',
* 'info': 'âšī¸',
* 'warn': 'â ī¸',
* 'error': 'â'
* }, 'đ');
*
* // Combining matchers
* const formatLogEntry = (level: string, message: string) => ({
* color: logLevelToColor(level),
* icon: logLevelToIcon(level),
* text: `${logLevelToIcon(level)} ${message}`
* });
* ```
*/
export declare function match<const Case extends string, const R extends ReadonlyRecord<Case, unknown>>(target: Case, cases: StrictPropertyCheck<R, Case>): R[Case];
export declare function match<const Case extends string, const R extends UnknownRecord, const D>(target: Case, cases: StrictPropertyCheck<R, Case>, defaultValue: IsLiteralUnionFullyCovered<Case, R> extends true ? never : D): ValueOf<R> | D;
/**
* @internal
* Helper type to ensure that an object `T` only contains keys specified in `ExpectedKeys`.
* If `T` has any keys not in `ExpectedKeys`, this type resolves to `never`.
* @template T The object type to check.
* @template ExpectedKeys The union of string literal types representing the allowed keys.
*/
type StrictPropertyCheck<T, ExpectedKeys extends PropertyKey> = RelaxedExclude<keyof T, ExpectedKeys> extends never ? T : never;
/**
* @internal
* Helper type to check if all cases in `Case` union are fully covered by keys in `R`.
* This checks bidirectional coverage: all Case members are in R, and no extra keys.
* @template Case A union of string literal types representing the possible cases.
* @template R A record type.
*/
type AllCasesCovered<Case extends PropertyKey, R> = TypeEq<Case, keyof R> extends true ? true : false;
/**
* @internal
* Helper type to check if Case is a literal union type and all cases are covered.
* @template Case A union of string literal types.
* @template R A record type.
*/
type IsLiteralUnionFullyCovered<Case extends PropertyKey, R extends UnknownRecord> = TypeEq<IsLiteralType<Case>, true> extends true ? AllCasesCovered<Case, R> : false;
/**
* @internal
* Helper type to determine if a given PropertyKey `T` is a literal type (e.g., 'a', 1)
* or a general type (e.g., string, number).
* @template T The PropertyKey type to check.
* @returns `true` if `T` is a literal type, `false` otherwise.
*/
type IsLiteralType<T extends PropertyKey> = string extends T ? false : number extends T ? false : symbol extends T ? false : true;
export {};
//# sourceMappingURL=match.d.mts.map