exiftool-vendored
Version:
Efficient, cross-platform access to ExifTool
176 lines (175 loc) • 7.33 kB
TypeScript
import { Maybe, Nullable } from "./Maybe";
export type StrEnumType<T extends string> = {
[K in T]: K;
};
/**
* Helper methods and properties for string enum types created with {@link strEnum}.
*
* Provides type-safe utilities for working with predefined string literal types,
* including validation, comparison, and transformation operations.
*
* @template T - The union of string literals that make up this enum
*/
export type StrEnumHelpers<T extends string> = {
/** Array of all valid enum values in declaration order */
values: T[];
/** Number of enum values */
length: number;
/**
* Synonym for {@link includes}. Checks if a string is a valid enum value.
* @param s - String to check (can be null/undefined)
* @returns Type predicate indicating if s is a valid enum value
*/
has(s: Nullable<string>): s is T;
/**
* Type-safe check if a string is a valid enum value (case-sensitive).
* @param s - String to check (can be null/undefined)
* @returns Type predicate indicating if s is a valid enum value
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.includes("red") // true
* Colors.includes("RED") // false
*/
includes(s: Nullable<string>): s is T;
/**
* Get enum value with case-insensitive matching.
* @param s - String to match (can be null/undefined)
* @returns Matching enum value or undefined if no match
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.getCI("RED") // "red"
* Colors.getCI("purple") // undefined
*/
getCI(s: Nullable<string>): Maybe<T>;
/**
* Create a new array containing only the specified enum values.
* @param t - Enum values to include
* @returns Array of specified enum values
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.pick("red", "blue") // ["red", "blue"]
*/
pick<O extends T>(...t: O[]): Extract<T, O>[];
/**
* Create a new array containing all enum values except the specified ones.
* @param t - Enum values to exclude
* @returns Array of remaining enum values
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.omit("green") // ["red", "blue"]
*/
omit<O extends T>(...t: O[]): Exclude<T, O>[];
/**
* Get the zero-based index of an enum value.
* @param s - Enum value to find (can be null/undefined)
* @returns Index of the value or undefined if not found
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.indexOf("green") // 1
* Colors.indexOf("purple") // undefined
*/
indexOf(s: Nullable<string>): Maybe<number>;
/**
* Get the ordinal position of an enum value, or length if not found.
* Useful for sorting where invalid values should sort last.
* @param s - Enum value to find (can be null/undefined)
* @returns Index of the value, or enum length if not found
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.ordinal("green") // 1
* Colors.ordinal("purple") // 3 (length)
*/
ordinal(s: Nullable<string>): number;
/**
* Synonym for {@link getCI}. Get enum value with case-insensitive matching.
* @param s - String to validate (can be null/undefined)
* @returns Valid enum value or undefined if no match
*/
toValid(s: Nullable<string>): Maybe<T>;
/**
* Find the first valid enum value from a list of candidates.
* @param arr - Array of potential enum values to check
* @returns First valid enum value found, or undefined if none match
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.firstValid("purple", "GREEN", "red") // "green" (case-insensitive match)
*/
firstValid(...arr: Nullable<string>[]): Maybe<T>;
/**
* Apply a function to a string if it's a valid enum value.
* @param s - String to check and potentially transform
* @param f - Function to apply if s is a valid enum value
* @returns Result of function application, or undefined if s is invalid
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.mapValid("red", color => color.toUpperCase()) // "RED"
* Colors.mapValid("purple", color => color.toUpperCase()) // undefined
*/
mapValid<R>(s: Nullable<string>, f: (t: T) => R): Maybe<R>;
/**
* Compare two strings based on their enum order.
* @param a - First string to compare
* @param b - Second string to compare
* @returns -1 if a < b, 0 if a === b, 1 if a > b, undefined if either is invalid
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.cmp("red", "green") // -1 (red comes before green)
* Colors.cmp("blue", "red") // 1 (blue comes after red)
*/
cmp(a: Nullable<string>, b: Nullable<string>): Maybe<number>;
/**
* Check if first enum value comes before second in declaration order.
* @param a - First enum value
* @param b - Second enum value
* @returns True if a comes before b in the enum declaration
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.lt("red", "green") // true
* Colors.lt("green", "red") // false
*/
lt(a: T, b: T): boolean;
/**
* Get the next enum value in declaration order.
* @param s - Current enum value
* @returns Next enum value, or undefined if s is the last value or invalid
* @example
* const Colors = strEnum("red", "green", "blue");
* Colors.next("red") // "green"
* Colors.next("blue") // undefined (no next value)
*/
next(s: Nullable<string>): Maybe<T>;
/**
* Create a new StrEnum with the values in reverse order.
*
* (This follows the new "toReversed" ES2023 naming convention for methods that return a new object)
* @returns New StrEnum with values in reverse declaration order
* @example
* const Colors = strEnum("red", "green", "blue");
* const Reversed = Colors.toReversed();
* Reversed.values // ["blue", "green", "red"]
*/
toReversed(): StrEnum<T>;
/**
* Makes the StrEnum iterable, allowing use in for...of loops and array destructuring.
* @returns Iterator that yields enum values in declaration order
* @example
* const Colors = strEnum("red", "green", "blue");
* for (const color of Colors) {
* console.log(color); // "red", "green", "blue"
* }
* const [first, second] = Colors; // first="red", second="green"
*/
[Symbol.iterator](): IterableIterator<T>;
/**
* String tag used by Object.prototype.toString() for better debugging.
* @example
* const Colors = strEnum("red", "green", "blue");
* Object.prototype.toString.call(Colors) // "[object StrEnum]"
*/
[Symbol.toStringTag]: "StrEnum";
};
export type StrEnum<T extends string> = StrEnumType<T> & StrEnumHelpers<T>;
export type StrEnumKeys<Type> = Type extends StrEnum<infer X> ? X : never;
export declare function strEnum<T extends string>(...o: T[]): StrEnum<T>;
export declare const Directions: StrEnum<"North" | "South" | "East" | "West">;
export type Direction = StrEnumKeys<typeof Directions>;