import type { Num, U } from './index.mjs'; /** * Returns the length of the given string S. * @example * ```ts * Length<'abc'> => 3 * ``` */ export type Length = LengthHelper; type LengthHelper = S extends '' ? Result : S extends `${string}${string}${string}${string}${string}${string}${string}${string}${string}${string}${infer Rest}` ? LengthHelper> : S extends `${string}${string}${string}${string}${string}${infer Rest}` ? LengthHelper> : S extends `${string}${infer Rest}` ? LengthHelper> : Result; /** * Convenience type to represent the concatenation of two string types. * @example * ```ts * Append<'abc', 'def'> => 'abcdef' * Append<'abc', 'd' | 'e'> => 'abcd' | 'abce' * ``` */ export type Append = `${Start}${End}`; /** * Convenience type to represent the concatenation of three string types. * @example * ```ts * AppendTwo<'abc', 'def', 'ghi'> => 'abcdefghi' * AppendTwo<'abc', 'd' | 'e', 'fgh'> => 'abcdfgh' | 'abcefgh' * ``` */ export type AppendTwo = `${Start}${Middle}${End}`; /** * Returns false if the given string is empty, true otherwise. * @example * ```ts * IsNonEmptyString<''> => false * IsNonEmptyString<'abc'> => true * ``` */ export type IsNonEmptyString = '' extends S ? false : true; /** * Returns never if the given string is empty, otherwise the given string. * @example * ```ts * NonEmptyString<''> => never * NonEmptyString<'abc'> => 'abc' * ``` */ export type NonEmptyString = '' extends S ? never : unknown; /** * If the given string does not start with the given `Start` type, returns false. * Otherwise, returns a tuple containing the matched start and the rest. * @example * ```ts * StartsWith<'abcd', 'ab'> => ['ab', 'cd'] * StartsWith<'abcd', 'd'> => false * StartsWith<'abcd', 'ab' | 'bc'> => ['ab', 'cd'] * StartsWith<'abcd', 'ab' | 'a'> => ['ab', 'cd'] | ['a', 'bcd'] * ``` */ export type StartsWith> = S extends Append ? S extends Append ? [StartInstance, Rest] : false : false; /** * If the given string does not end with the given `End` type, returns false. * Otherwise, returns a tuple containing the start and the matched end. * @example * ```ts * EndsWith<'abcd', 'cd'> => ['ab', 'cd'] * EndsWith<'abcd', 'a'> => false * EndsWith<'abcd', 'cd' | 'de'> => ['ab', 'cd'] * EndsWith<'abcd', 'cd' | 'd'> => ['ab', 'cd'] | ['abc', 'd'] * ``` */ export type EndsWith> = S extends Append ? S extends Append ? [Start, EndInstance] : false : false; /** * Returns false if the given string does not contain the given `Middle` type, * or a 3-tuple containing the start, the matched middle, and the rest. * @example * ```ts * SplitAt<'abcd', 'bc'> => ['a', 'bc', 'd'] * SplitAt<'abcd', 'ef'> => false * SplitAt<'abcd', 'b' | 'c'> => ['a', 'b', 'cd'] | ['ab', 'c', 'd'] * ``` */ export type SplitAt> = S extends AppendTwo ? S extends AppendTwo ? [Start, MiddleInstance, End] : false : ['', '', S]; /** * Returns a string containing all the elements that do not match the given Sub type. * @example * ```ts * FilterNot<'abcd', 'b'> => 'acd' * FilterNot<'abcd', 'b' | 'd'> => 'ac' * ``` */ export type FilterNot> = FilterNotHelper; type FilterNotHelper, Result extends string> = S extends '' ? Result : S extends Append ? FilterNotHelper : S extends Append ? FilterNotHelper> : ''; /** * Returns a string containing all the elements that match the given Sub type. * @example * ```ts * Filter<'abcd', 'b'> => 'b' * Filter<'abcd', 'b' | 'd'> => 'bd' * ``` */ export type Filter> = FilterHelper; type FilterHelper, Result extends string> = S extends '' ? Result : StartsWith extends [infer SubInstance, infer Rest] ? FilterHelper> : S extends Append ? FilterHelper : ''; /** * Replaces, in the given string, all matches with Sub with the given Repl. * @example * ```ts * ReplaceAll<'abcba', 'b', '_'> => 'a_c_a' * ReplaceAll<'abcba', 'b' | 'c', '_'> => 'a___a' * ``` */ export type ReplaceAll, Repl extends string> = S extends '' ? '' : S extends Append ? Append> : S extends Append ? Append> : never; /** * Replaces, in the given string, the first match with Sub with the given Repl. * Returns never if there was no match. * @example * ```ts * ReplaceFirst<'abcba', 'b', '_'> => 'a_cba' * ReplaceFirst<'abcba', 'b' | 'c', '_'> => 'a_cba' * ``` */ export type ReplaceFirst, Repl extends string> = S extends '' ? never : S extends Append ? Append : S extends Append ? Append> : never; /** * Replaces, in the given string, the last match with Sub with the given Repl. * Returns never if there was no match. * @example * ```ts * ReplaceLast<'abcba', 'b', '_'> => 'abc_a' * ReplaceLast<'abcba', 'b' | 'c', '_'> => 'abc_a' * ``` */ export type ReplaceLast, Repl extends string> = ReplaceLastHelper; type ReplaceLastHelper, Repl extends string, Replaced extends boolean> = S extends '' ? Replaced extends true ? '' : never : StartsWith extends [infer SubInstance, infer Rest] ? ReplaceLastHelper extends infer Result ? Append : never : S extends Append ? Append> : never; /** * Returns the amount of times the given `Sub` type is encountered in the given string. * @example * ```ts * Count<'abcba', 'c'> => 1 * Count<'abcba', 'a' | 'c'> => 3 * Count<'abcba', 'q'> => 0 * ``` */ export type Count> = CountHelper; type CountHelper, Result extends number> = S extends '' ? Result : S extends Append ? CountHelper> : S extends Append ? CountHelper : Result; /** * Returns true if the given string contains the given Amount (default 1) of Sub types. * @example * ```ts * Contains<'abcba', 'b'> => true * Contains<'abcba', 'b', 2> => true * Contains<'abcba', 'b', 3> => false * Contains<'abcba', 'q'> => false * ``` */ export type Contains, Amount extends number = 1> = Amount extends 0 ? true : S extends Append ? Contains> : S extends Append ? Contains : false; /** * Returns true if the given string does not contain the given Amount (default 1) of Sub types. * @example * ```ts * NotContains<'abcba', 'b'> => false * NotContains<'abcba', 'b', 2> => false * NotContains<'abcba', 'b', 3> => true * NotContains<'abcba', 'q'> => true * ``` */ export type NotContains, Amount extends number = 1> = Contains extends false ? true : false; export type RepeatTimes> = RepeatTimesHelper; type RepeatTimesHelper, Result extends [number, string]> = S extends '' ? [...Result, S] : StartsWith extends [infer SubInstance, infer Rest] ? RepeatTimesHelper, Append ]> : [...Result, S]; /** * Returns a tuple containing the matched part and the rest of the given string if the string * start repeats the given Sub at least N times. * @example * ```ts * RepeatAtLeastTimes<'aabc', 'a', 0> => ['', 'aabc'] * RepeatAtLeastTimes<'aabc', 'a', 1> => ['a', 'abc'] * RepeatAtLeastTimes<'aabc', 'a', 3> => false * RepeatAtLeastTimes<'aabc', 'a' | 'b', 3> => ['aab', 'c'] * ``` */ export type RepeatAtLeastTimes, N extends number> = RepeatAtLeastTimesHelper; type RepeatAtLeastTimesHelper, N extends number, Processed extends string> = N extends 0 ? [Processed, S] : S extends '' ? false : StartsWith extends [infer SubInstance, infer Rest] ? RepeatAtLeastTimesHelper, Append> : false; /** * Returns a tuple containing the matched part and the rest of the given string if the string * start repeats the given Sub at most N times. * @example * ```ts * RepeatAtMostTimes<'aabc', 'a', 0> => false * RepeatAtMostTimes<'aabc', 'a', 1> => false * RepeatAtMostTimes<'aabc', 'a', 3> => ['aa', 'bc'] * RepeatAtMostTimes<'aabc', 'a' | 'b', 3> => ['aab', 'c'] * ``` */ export type RepeatAtMostTimes, N extends number> = RepeatAtMostTimesHelper; type RepeatAtMostTimesHelper, N extends number, Processed extends string> = S extends Append ? N extends 0 ? false : S extends Append ? RepeatAtMostTimesHelper, Append> : never : [Processed, S]; /** * Returns a tuple containing the matched part and the rest of the given string if the string * start repeats the given Sub exactly N times. * @example * ```ts * RepeatExactTimes<'aabc', 'a', 0> => false * RepeatExactTimes<'aabc', 'a', 1> => false * RepeatExactTimes<'aabc', 'a', 2> => ['aa', 'bc'] * RepeatExactTimes<'aabc', 'a', 3> => false * RepeatExactTimes<'aabc', 'a' | 'b', 3> => ['aab', 'c'] * ``` */ export type RepeatExactTimes, N extends number> = RepeatExactTimesHelper; type RepeatExactTimesHelper, N extends number, Processed extends string> = S extends Append ? N extends 0 ? false : S extends Append ? RepeatExactTimesHelper, Append> : never : N extends 0 ? [Processed, S] : false; /** * Returns the first N characters of the given string, or false if the string does * not have enough characters. * @example * ```ts * TakeStrict<'abcd', 2> => 'ab' * TakeStrict<'abcd', 5> => false * ``` */ export type TakeStrict = TakeStrictHelper; type TakeStrictHelper = N extends 0 ? Result : S extends Append ? TakeStrictHelper, Append> : false; /** * Returns the first N characters of the given string, or the given * string if it does not have enough characters. * @example * ```ts * Take<'abcd', 2> => 'ab' * Take<'abcd', 5> => 'abcd' * ``` */ export type Take = TakeHelper; type TakeHelper = N extends 0 ? Result : S extends Append ? TakeHelper, Append> : Result; /** * Returns part of the string as long as its parts match Sub. * @example * ```ts * TakeWhile<'aabc', 'a'> => 'aa' * TakeWhile<'aabc', 'a' | 'b'> => 'aab' * TakeWhile<'aabc', 'q'> => '' * ``` */ export type TakeWhile> = TakeWhileHelper; type TakeWhileHelper, Result extends string> = StartsWith extends [infer SubInstance, infer Rest] ? TakeWhileHelper> : Result; /** * Skips part of the string as long as its parts match Sub. * @example * ```ts * DropWhile<'aabc', 'a'> => 'bc' * DropWhile<'aabc', 'a' | 'b'> => 'c' * DropWhile<'aabc', 'q'> => 'aabc' * ``` */ export type DropWhile = S extends Append ? DropWhile : S; /** * Returns the given string reversed. * @example * ```ts * Reverse<'abcd'> => 'dcba' * ``` */ export type Reverse = ReverseHelper; type ReverseHelper = S extends Append ? ReverseHelper> : Result; /** * Returns the given string without the first N characters, or false if the * string has less characters. * @example * ```ts * DropStrict<'abcd', 2> => 'cd' * DropStrict<'abcd', 5> => false * ``` */ export type DropStrict = N extends 0 ? S : S extends Append ? DropStrict> : false; /** * Returns the given string without the first N characters, or an empty string if the * string has less characters. * @example * ```ts * Drop<'abcd', 2> => 'cd' * Drop<'abcd', 5> => '' * ``` */ export type Drop = N extends 0 ? S : S extends Append ? Drop> : S; /** * Returns the first character of the given string, or false if the string is empty. * @example * ```ts * First<'abc'> => 'a' * First<''> => false * ``` */ export type First = S extends Append ? First : false; /** * Returns all but the first character of the given string, or false if the string is empty. * @example * ```ts * Tail<'abcd'> => 'bcd' * Tail<''> => false * ``` */ export type Tail = S extends Append ? Rest : false; /** * Returns all but the last character of the given string, or false if the string is empty. * @example * ```ts * Init<'abcd'> => 'abc' * Init<''> => false * ``` */ export type Init = InitHelper; type InitHelper = S extends Append ? U.Extends>> : false; /** * Returns the last character of the given string, or false if the string if empty. * @example * ```ts * Last<'abcd'> => 'd' * Last<''> => false * ``` */ export type Last = S extends Append ? U.Extends> : false; /** * Returns the character in the given string at the given Index, or false if the index * is out of bounds. * @example * ```ts * CharAt<'abcd', 1> => 'b' * CharAt<'abcd', 5> => false * ``` */ export type CharAt = S extends Append ? U.Extends>> : false; export {};