@visulima/string
Version:
Functions for manipulating strings.
42 lines (39 loc) • 8.68 kB
text/typescript
type TupleOf<L extends number, T = unknown, Result extends any[] = []> = Result["length"] extends L ? Result : TupleOf<L, T, [...Result, T]>;
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;
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;
type EndsWithNoPositionType<T extends string, S extends string> = StartsWith<Reverse<T>, Reverse<S>>;
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 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 Reverse<T extends string, Accumulator extends string = ""> = T extends `${infer Head}${infer Tail}` ? Reverse<Tail, `${Head}${Accumulator}`> : Accumulator extends "" ? T : `${T}${Accumulator}`;
type Any<BoolArray extends boolean[]> = BoolArray extends [infer Head extends boolean, ...infer Rest extends boolean[]] ? IsBooleanLiteral<Head> extends true ? Head extends true ? true : Any<Rest> : Any<Rest> : false;
type All<BoolArray extends boolean[]> = IsBooleanLiteral<BoolArray[number]> extends true ? BoolArray extends [infer Head extends boolean, ...infer Rest extends boolean[]] ? Head extends true ? Any<Rest> : false : true : 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 CharAt<T extends string, Index extends number> = All<[IsStringLiteral<T>, IsNumberLiteral<Index>]> extends true ? Split<T>[Index] : string;
type Concat<T extends string[]> = Join<T>;
type EndsWith<T extends string, S extends string, P extends number | undefined = undefined> = P extends number ? InternalEndsWithType<T, S, P> : EndsWithNoPositionType<T, S>;
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 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 Length<T extends string> = IsStringLiteral<T> extends true ? Split<T>["length"] : number;
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 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 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 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 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 Slice<T extends string, StartIndex extends number = 0, EndIndex extends number | undefined = undefined> = EndIndex extends number ? InternalSliceType<T, StartIndex, EndIndex> : SliceStartType<T, StartIndex>;
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 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 TrimEnd<T extends string> = T extends `${infer Rest} ` ? TrimEnd<Rest> : T;
type TrimStart<T extends string> = T extends ` ${infer Rest}` ? TrimStart<Rest> : T;
type Trim<T extends string> = TrimEnd<TrimStart<T>>;
type NodeLocale = "af" | "am" | "ar" | "az" | "be" | "bg" | "bn" | "bs" | "ca" | "cs" | "cy" | "da" | "de" | "el" | "en" | "en-AU" | "en-CA" | "en-GB" | "en-US" | "es" | "es-ES" | "et" | "fa" | "fi" | "fil" | "fr" | "ga" | "gl" | "gu" | "he" | "hi" | "hr" | "hu" | "hy" | "id" | "is" | "it" | "ja" | "ka" | "kk" | "km" | "kn" | "ko" | "ky" | "lo" | "lt" | "lv" | "mk" | "ml" | "mn" | "mr" | "ms" | "mt" | "ne" | "nl" | "no" | "pa" | "pl" | "pt" | "pt-BR" | "pt-PT" | "ro" | "ru" | "si" | "sk" | "sl" | "sq" | "sr" | "sv" | "ta" | "te" | "th" | "tr" | "uk" | "ur" | "uz" | "vi" | "zh" | "zh-CN" | "zh-HK" | "zh-TW";
type ToLowerCase<T extends string> = IsStringLiteral<T> extends true ? Lowercase<T> : string;
type ToUpperCase<T extends string> = IsStringLiteral<T> extends true ? Uppercase<T> : string;
export { type All as A, type CharAt as C, type EndsWith as E, type Includes as I, type Join as J, type Length as L, Math as M, type NodeLocale as N, type PadEnd as P, type Replace as R, type Slice as S, type ToLowerCase as T, type Concat as a, type PadStart as b, type ReplaceAll as c, type Split as d, type StartsWith as e, type ToUpperCase as f, type Trim as g, type TrimEnd as h, type TrimStart as i, type Any as j, type IsBooleanLiteral as k, type IsNumberLiteral as l, type IsStringLiteral as m, type IsStringLiteralArray as n, type Repeat as o, type Reverse as p };