
/**
* Creates a tuple type of specified length filled with a given type.
* @template L - The desired length of the tuple
* @template T - The type to fill the tuple with (defaults to unknown)
* @template Result - Internal accumulator for recursive type building
* @returns A tuple type of length L filled with type T
*/
type TupleOf<L extends number, T = unknown, Result extends any[] = []> = Result["length"] extends L ? Result : TupleOf<L, T, [...Result, T]>;
/**
* Internal type for implementing string slicing with both start and end indices.
* Handles edge cases and type safety for string literal types.
* @template T - The input string type
* @template StartIndex - The starting index for the slice
* @template EndIndex - The ending index for the slice
* @template Result - Internal accumulator for building the result string
*/
type InternalSliceType<T extends string, StartIndex extends number, EndIndex extends number, Result extends string = ""> = IsNumberLiteral<EndIndex | StartIndex> extends true ? T extends `${infer Head}${infer Rest}` ? IsStringLiteral<Head> extends true ? StartIndex extends 0 ? EndIndex extends 0 ? Result : InternalSliceType<Rest, 0, Math.Subtract<Math.GetPositiveIndex<T, EndIndex>, 1>, `${Result}${Head}`> : InternalSliceType<Rest, Math.Subtract<Math.GetPositiveIndex<T, StartIndex>, 1>, Math.Subtract<Math.GetPositiveIndex<T, EndIndex>, 1>, Result> : EndIndex | StartIndex extends 0 ? Result : string : IsStringLiteral<T> extends true ? Result : EndIndex | StartIndex extends 0 ? Result : string : string;
/**
* Internal type for implementing string slicing with only a start index.
* Provides type-safe string slicing functionality for string literal types.
* @template T - The input string type
* @template StartIndex - The starting index for the slice
* @template Result - Internal accumulator for building the result string
*/
type SliceStartType<T extends string, StartIndex extends number, Result extends string = ""> = IsNumberLiteral<StartIndex> extends true ? T extends `${infer Head}${infer Rest}` ? IsStringLiteral<Head> extends true ? StartIndex extends 0 ? T : SliceStartType<Rest, Math.Subtract<Math.GetPositiveIndex<T, StartIndex>, 1>, Result> : string : IsStringLiteral<T> extends true ? Result : StartIndex extends 0 ? Result : string : string;
type InternalEndsWithType<T extends string, S extends string, P extends number> = All<[IsStringLiteral<S>, IsNumberLiteral<P>]> extends true ? Math.IsNegative<P> extends false ? P extends Length<T> ? IsStringLiteral<T> extends true ? S extends Slice<T, Math.Subtract<Length<T>, Length<S>>, Length<T>> ? true : false : EndsWithNoPositionType<Slice<T, 0, P>, S> : EndsWithNoPositionType<Slice<T, 0, P>, S> : false : boolean;
/**
* Internal type for implementing EndsWith functionality without a position parameter.
* Uses string reversal to check if a string ends with another string.
* @template T - The string to check
* @template S - The suffix to check for
*/
type EndsWithNoPositionType<T extends string, S extends string> = StartsWith<Reverse<T>, Reverse<S>>;
/**
* Namespace containing type-level mathematical operations.
* These utilities provide type-safe arithmetic and number manipulation.
*/
declare namespace Math {
  type Subtract<A extends number, B extends number> = number extends A | B ? number : TupleOf<A> extends [...infer U, ...TupleOf<B>] ? U["length"] : 0;
  type IsNegative<T extends number> = number extends T ? boolean : `${T}` extends `-${number}` ? true : false;
  type Abs<T extends number> = `${T}` extends `-${infer U extends number}` ? U : T;
  type GetPositiveIndex<T extends string, I extends number> = IsNegative<I> extends false ? I : Subtract<Length<T>, Abs<I>>;
}
/**
* Type predicate that determines if a number type is a literal type rather than the general 'number' type.
* For example: IsNumberLiteral&lt;42> is true, but IsNumberLiteral&lt;number> is false.
* @template T - The number type to check
* @returns true if T is a number literal type, false otherwise
*/
type IsNumberLiteral<T extends number> = [T] extends [number] ? ([number] extends [T] ? false : true) : false;
type IsBooleanLiteral<T extends boolean> = [T] extends [boolean] ? ([boolean] extends [T] ? false : true) : false;
/**
* Type-level string reversal utility.
* Recursively builds the reversed string using template literal types.
* @template T - The string type to reverse
* @template Accumulator - Internal accumulator for building the reversed string
* @returns A type representing the reversed string
* @example
* type ReversedHello = Reverse<'hello'> // type ReversedHello = 'olleh'
*/
type Reverse<T extends string, Accumulator extends string = ""> = T extends `${infer Head}${infer Tail}` ? Reverse<Tail, `${Head}${Accumulator}`> : Accumulator extends "" ? T : `${T}${Accumulator}`;
/**
* Type predicate that checks if all elements in a boolean array type are the literal 'true'.
* Distinguishes between literal true/false and the general boolean type.
* @template T - Array of boolean types to check
* @returns true if all elements are the literal true, false otherwise
* @example
* type AllTrue = All<[true, true]> // type AllTrue = true
* type NotAllTrue = All<[true, false]> // type NotAllTrue = false
*/
type All<BoolArray extends boolean[]> = IsBooleanLiteral<BoolArray[number]> extends true ? BoolArray extends [infer Head extends boolean, ...infer Rest extends boolean[]] ? Head extends true ? All<Rest> : false : true : false;
/**
* Type predicate that determines if a string type is a literal type rather than the general 'string' type.
* @template T - The string type to check
* @returns true if T is a string literal type, false if it's the general string type
* @example
* type IsLiteral = IsStringLiteral<'hello'> // type IsLiteral = true
* type NotLiteral = IsStringLiteral<string> // type NotLiteral = false
*/
type IsStringLiteral<T extends string> = [T] extends [string] ? [string] extends [T] ? false : Uppercase<T> extends Uppercase<Lowercase<T>> ? Lowercase<T> extends Lowercase<Uppercase<T>> ? true : false : false : false;
type IsStringLiteralArray<StringArray extends ReadonlyArray<string>> = IsStringLiteral<StringArray[number]> extends true ? true : false;
/**
* Type-safe utility to get the character at a specific index in a string literal type.
* @template T - The string type to extract a character from
* @template Index - The numeric index of the desired character
* @returns The character type at the specified index, or never if the index is invalid
* @example
* type FirstChar = CharAt<'hello', 0> // type FirstChar = 'h'
*/
type CharAt<T extends string, Index extends number> = All<[IsStringLiteral<T>, IsNumberLiteral<Index>]> extends true ? Split<T>[Index] : string;
/**
* Type-level string concatenation for tuples of string literals.
* Joins all strings in the tuple into a single string type.
* @template T - Tuple of string types to concatenate
* @returns A single string type representing the concatenated result
* @example
* type Combined = Concat<['hello', ' ', 'world']> // type Combined = 'hello world'
*/
type Concat<T extends string[]> = Join<T>;
/**
* Type-level implementation of string.endsWith() functionality.
* Checks if a string type ends with another string type at a given position.
* @template T - The string type to check
* @template S - The suffix to check for
* @template P - Optional position at which to end the search
* @returns A boolean type indicating if T ends with S at position P
* @example
* type EndsWithWorld = EndsWith<'hello world', 'world'> // type EndsWithWorld = true
* type DoesNotEnd = EndsWith<'hello world', 'hello'> // type DoesNotEnd = false
*/
type EndsWith<T extends string, S extends string, P extends number | undefined = undefined> = P extends number ? InternalEndsWithType<T, S, P> : EndsWithNoPositionType<T, S>;
/**
* Type-level implementation of string.includes() functionality.
* Determines if one string type contains another string type starting at an optional position.
* @template T - The string type to search within
* @template S - The string type to search for
* @template P - Optional position to start the search from
* @returns A boolean type indicating if S is found within T starting at P
* @example
* type HasWorld = Includes<'hello world', 'world'> // type HasWorld = true
* type NoWorld = Includes<'hello', 'world'> // type NoWorld = false
*/
type Includes<T extends string, S extends string, P extends number = 0> = string extends S | T ? boolean : Math.IsNegative<P> extends false ? P extends 0 ? T extends `${string}${S}${string}` ? true : false : Includes<Slice<T, P>, S> : Includes<T, S>;
/**
* Type-level implementation of Array.join() functionality for string tuples.
* Combines string literal types in a tuple using a delimiter.
* @template T - Tuple of string types to join
* @template Delimiter - The delimiter to insert between elements
* @returns A string type representing the joined result
* @example
* type Joined = Join<['a', 'b', 'c'], '.'> // type Joined = 'a.b.c'
*/
type Join<T extends ReadonlyArray<string>, Delimiter extends string = ""> = All<[IsStringLiteralArray<T>, IsStringLiteral<Delimiter>]> extends true ? T extends readonly [infer First extends string, ...infer Rest extends string[]] ? Rest extends [] ? First : `${First}${Delimiter}${Join<Rest, Delimiter>}` : "" : string;
/**
* Type-level utility to compute the length of a string literal type.
* @template T - The string type to measure
* @returns A number literal type representing the string's length
* @example
* type Len = Length<'hello'> // type Len = 5
*/
type Length<T extends string> = IsStringLiteral<T> extends true ? Split<T>["length"] : number;
/**
* Type-level implementation of string.padEnd() functionality.
* Adds padding to the end of a string type until it reaches a specified length.
* @template T - The string type to pad
* @template Times - Target total length of the padded string
* @template Pad - The string to use as padding (defaults to space)
* @returns A string type with the padding added to the end
* @example
* type Padded = PadEnd<'hello', 7, '_'> // type Padded = 'hello__'
*/
type PadEnd<T extends string, Times extends number = 0, Pad extends string = " "> = All<[IsStringLiteral<Pad | T>, IsNumberLiteral<Times>]> extends true ? Math.IsNegative<Times> extends false ? Math.Subtract<Times, Length<T>> extends infer Missing extends number ? `${T}${Slice<Repeat<Pad, Missing>, 0, Missing>}` : never : T : string;
/**
* Type-level implementation of string.padStart() functionality.
* Adds padding to the beginning of a string type until it reaches a specified length.
* @template T - The string type to pad
* @template Times - Target total length of the padded string
* @template Pad - The string to use as padding (defaults to space)
* @returns A string type with the padding added to the start
* @example
* type Padded = PadStart<'hello', 7, '_'> // type Padded = '__hello'
*/
type PadStart<T extends string, Times extends number = 0, Pad extends string = " "> = All<[IsStringLiteral<Pad | T>, IsNumberLiteral<Times>]> extends true ? Math.IsNegative<Times> extends false ? Math.Subtract<Times, Length<T>> extends infer Missing extends number ? `${Slice<Repeat<Pad, Missing>, 0, Missing>}${T}` : never : T : string;
/**
* Type-level implementation of string.repeat() functionality.
* Creates a new string type by repeating the input string a specified number of times.
* @template T - The string type to repeat
* @template Times - The number of times to repeat the string
* @returns A string type containing T repeated Times times
* @example
* type Repeated = Repeat<'abc', 2> // type Repeated = 'abcabc'
*/
type Repeat<T extends string, Times extends number = 0> = All<[IsStringLiteral<T>, IsNumberLiteral<Times>]> extends true ? Times extends 0 ? "" : Math.IsNegative<Times> extends false ? Join<TupleOf<Times, T>> : never : string;
/**
* Type-level implementation of string.replaceAll() functionality.
* Replaces all occurrences of a substring with another string.
* @template Sentence - The string type to perform replacements on
* @template Lookup - The string or RegExp pattern to search for. When a RegExp is used, the result type widens to string.
* @template Replacement - The string type to replace matches with
* @returns A string type with all occurrences of Lookup replaced with Replacement. When Lookup is a RegExp, returns string.
* @example
* type Replaced = ReplaceAll<'hello hello', 'hello', 'hi'> // type Replaced = 'hi hi'
*/
type ReplaceAll<Sentence extends string, Lookup extends RegExp | string, Replacement extends string = ""> = Lookup extends string ? IsStringLiteral<Lookup | Replacement | Sentence> extends true ? Sentence extends `${infer Rest}${Lookup}${infer Rest2}` ? `${Rest}${Replacement}${ReplaceAll<Rest2, Lookup, Replacement>}` : Sentence : string : string;
/**
* Type-level implementation of string.replace() functionality.
* Replaces the first occurrence of a substring with another string.
* @template Sentence - The string type to perform replacement on
* @template Lookup - The string or RegExp pattern to search for. When a RegExp is used, the result type widens to string.
* @template Replacement - The string type to replace the match with
* @returns A string type with the first occurrence of Lookup replaced with Replacement. When Lookup is a RegExp, returns string.
* @example
* type Replaced = Replace<'hello hello', 'hello', 'hi'> // type Replaced = 'hi hello'
*/
type Replace<Sentence extends string, Lookup extends RegExp | string, Replacement extends string = ""> = Lookup extends string ? IsStringLiteral<Lookup | Replacement | Sentence> extends true ? Sentence extends `${infer Rest}${Lookup}${infer Rest2}` ? `${Rest}${Replacement}${Rest2}` : Sentence : string : string;
/**
* Type-level implementation of string.slice() functionality.
* Extracts a portion of a string type between start and end indices.
* @template T - The string type to slice
* @template StartIndex - The starting index of the slice
* @template EndIndex - The ending index of the slice (optional)
* @returns A string type containing the characters between the indices
* @example
* type Sliced = Slice<'hello world', 0, 5> // type Sliced = 'hello'
* type ToEnd = Slice<'hello world', 6> // type ToEnd = 'world'
*/
type Slice<T extends string, StartIndex extends number = 0, EndIndex extends number | undefined = undefined> = EndIndex extends number ? InternalSliceType<T, StartIndex, EndIndex> : SliceStartType<T, StartIndex>;
/**
* Type-level implementation of string.split() functionality.
* Splits a string type into a tuple of string types based on a delimiter.
* @template T - The string type to split
* @template Delimiter - The string type to use as a separator
* @returns A tuple type containing the split string parts
* @example
* type Parts = Split<'a,b,c', ','> // type Parts = ['a', 'b', 'c']
*/
type Split<T extends string, Delimiter extends string = ""> = IsStringLiteral<Delimiter | T> extends true ? T extends `${infer First}${Delimiter}${infer Rest}` ? [First, ...Split<Rest, Delimiter>] : T extends "" ? [] : [T] : string[];
/**
* Type-level implementation of string.startsWith() functionality.
* Checks if a string type begins with another string type at a given position.
* @template T - The string type to check
* @template S - The prefix to check for
* @template P - Optional position at which to start the search
* @returns A boolean type indicating if T starts with S at position P
* @example
* type StartsWithHello = StartsWith<'hello world', 'hello'> // type StartsWithHello = true
* type DoesNotStart = StartsWith<'hello world', 'world'> // type DoesNotStart = false
*/
type StartsWith<T extends string, S extends string, P extends number = 0> = All<[IsStringLiteral<S>, IsNumberLiteral<P>]> extends true ? Math.IsNegative<P> extends false ? P extends 0 ? S extends `${infer SHead}${infer SRest}` ? T extends `${infer THead}${infer TRest}` ? IsStringLiteral<SHead | THead> extends true ? THead extends SHead ? StartsWith<TRest, SRest> : false : boolean : IsStringLiteral<T> extends true ? false : boolean : true : StartsWith<Slice<T, P>, S> : StartsWith<T, S> : boolean;
/**
* Type-level implementation of string.trimEnd() functionality.
* Removes whitespace characters from the end of a string type.
* @template T - The string type to trim
* @returns A string type with trailing whitespace removed
* @example
* type Trimmed = TrimEnd<'hello  '> // type Trimmed = 'hello'
*/
type TrimEnd<T extends string> = T extends `${infer Rest} ` ? TrimEnd<Rest> : T;
/**
* Type-level implementation of string.trimStart() functionality.
* Removes whitespace characters from the beginning of a string type.
* @template T - The string type to trim
* @returns A string type with leading whitespace removed
* @example
* type Trimmed = TrimStart<'  hello'> // type Trimmed = 'hello'
*/
type TrimStart<T extends string> = T extends ` ${infer Rest}` ? TrimStart<Rest> : T;
/**
* Type-level implementation of string.trim() functionality.
* Removes whitespace characters from both ends of a string type.
* @template T - The string type to trim
* @returns A string type with both leading and trailing whitespace removed
* @example
* type Trimmed = Trim<'  hello  '> // type Trimmed = 'hello'
*/
type Trim<T extends string> = TrimEnd<TrimStart<T>>;
/**
* Type-level implementation of string.toLowerCase() functionality.
* Converts all alphabetic characters in a string type to lowercase.
* @template T - The string type to convert
* @returns A string type with all characters converted to lowercase
* @example
* type Lower = ToLowerCase<'HELLO'> // type Lower = 'hello'
*/
type ToLowerCase<T extends string> = IsStringLiteral<T> extends true ? Lowercase<T> : string;
/**
* Type-level implementation of string.toUpperCase() functionality.
* Converts all alphabetic characters in a string type to uppercase.
* @template T - The string type to convert
* @returns A string type with all characters converted to uppercase
* @example
* type Upper = ToUpperCase<'hello'> // type Upper = 'HELLO'
*/
type ToUpperCase<T extends string> = IsStringLiteral<T> extends true ? Uppercase<T> : string;
declare global {
  interface String {
    /**
     * Returns the character at the specified index.
     * @param index The zero-based index of the desired character.
     */
    charAt<T extends string = string, I extends number = number>(this: T, index: I): CharAt<T, I>;

    /**
     * Returns a string that contains the concatenation of two or more strings.
     * @param strings The strings to append to the end of the string.
     */
    concat<T extends string = string, S extends string[] | string = string>(this: T, ...strings: S extends string ? [S] : S extends string[] ? S : never): S extends string ? Concat<[T, S]> : S extends string[] ? Concat<[T, ...S]> : never;

    /**
     * Returns true if the sequence of elements of searchString converted to a String is the
     * same as the corresponding elements of this object (converted to a String) starting at
     * position. Otherwise returns false.
     */
    endsWith<T extends string = string, S extends string = string, P extends number | undefined = undefined>(this: T, searchString: S, position?: P): EndsWith<T, S, P>;

    /**
     * Returns true if searchString appears as a substring of the result of converting this
     * object to a String, at one or more positions that are greater than or equal to
     * position; otherwise, returns false.
     * @param searchString
     * @param position If position is undefined, 0 is assumed, so as to search all of the String.
     */
    includes<T extends string = string, S extends string = string, P extends number = 0>(this: T, searchString: S, position?: P): Includes<T, S, P>;

    /**
     * Returns the length of a String object.
     */
    length: Length<this>;

    /**
     * Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length.
     * The padding is applied from the end (right) of the current string.
     * @param maxLength The length of the resulting string once the current string has been padded.
     * @param fillString The string to pad the current string with. If this string is too long, it will be truncated and the left-most part will be applied.
     */
    padEnd<T extends string = string, N extends number = number, P extends string = " ">(this: T, maxLength: N, fillString?: P): PadEnd<T, N, P>;

    /**
     * Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length.
     * The padding is applied from the start (left) of the current string.
     * @param maxLength The length of the resulting string once the current string has been padded.
     * @param fillString The string to pad the current string with. If this string is too long, it will be truncated and the left-most part will be applied.
     */
    padStart<T extends string = string, N extends number = number, P extends string = " ">(this: T, maxLength: N, fillString?: P): PadStart<T, N, P>;

    /**
     * Replace text in a string, using a regular expression or search string.
     * @param searchValue A string to search for.
     * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
     */
    replace<T extends string = string, S extends RegExp | string = string, R extends string = string>(this: T, searchValue: S, replaceValue: R): Replace<T, S, R>;

    /**
     * Replace all instances of a substring in a string, using a regular expression or search string.
     * @param searchValue A string to search for.
     * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
     */
    replaceAll<T extends string = string, S extends RegExp | string = string, R extends string = string>(this: T, searchValue: S, replaceValue: R): ReplaceAll<T, S, R>;

    /**
     * Returns a section of a string.
     * @param start The index to the beginning of the specified portion of stringObj.
     * @param end The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end.
     */
    slice<T extends string = string, S extends number = number, E extends number | undefined = undefined>(this: T, start?: S, end?: E): Slice<T, S, E>;

    /**
     * Split a string into substrings using the specified separator and return them as an array.
     * @param separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.
     */
    split<T extends string = string, S extends string = string>(this: T, separator: S): Split<T, S>;

    /**
     * Returns true if the sequence of elements of searchString converted to a String is the
     * same as the corresponding elements of this object (converted to a String) starting at
     * position. Otherwise returns false.
     */
    startsWith<T extends string = string, S extends string = string, P extends number = 0>(this: T, searchString: S, position?: P): StartsWith<T, S, P>;

    /**
     * Converts all alphabetic characters in a string to lowercase.
     */
    toLowerCase<T extends string = string>(this: T): ToLowerCase<T>;

    /**
     * Converts all alphabetic characters in a string to uppercase.
     */
    toUpperCase<T extends string = string>(this: T): ToUpperCase<T>;

    /**
     * Returns a string with all whitespace removed from both ends of a string.
     */
    trim<T extends string = string>(this: T): Trim<T>;

    /**
     * Returns a string with all whitespace removed from the end of a string.
     */
    trimEnd<T extends string = string>(this: T): TrimEnd<T>;

    /**
     * Returns a string with all whitespace removed from the start of a string.
     */
    trimStart<T extends string = string>(this: T): TrimStart<T>;
  }
}
