@rzl-zone/utils-js
Version:
A modern, lightweight set of JavaScript utility functions for everyday development, crafted to enhance code readability and maintainability.
918 lines (917 loc) • 109 kB
TypeScript
/** --------------------------------------------------
* * ***A union type of all valid named CSS colors including `transparent`.***
* --------------------------------------------------
*
* This type includes standard color names as defined in the CSS Color Module Specification,
* and can be used for validating CSS color inputs in strongly typed UI libraries, themes, or design systems.
*
* It ensures that only recognized, browser-supported color keywords are accepted.
*
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/named
* @see https://drafts.csswg.org/css-color-4/#named-colors
*
* @example
* const textColor: ColorCssValidBase = "rebeccapurple"; // ✅ valid
* const invalidColor: ColorCssValidBase = "superblue"; // ❌ Type error
*/
type ColorCssValidBase="aliceblue" | "antiquewhite" | "aqua" | "aquamarine" | "azure" | "beige" | "bisque" | "black" | "blanchedalmond" | "blue" | "blueviolet" | "brown" | "burlywood" | "cadetblue" | "chartreuse" | "chocolate" | "coral" | "cornflowerblue" | "cornsilk" | "crimson" | "cyan" | "darkblue" | "darkcyan" | "darkgoldenrod" | "darkgray" | "darkgreen" | "darkgrey" | "darkkhaki" | "darkmagenta" | "darkolivegreen" | "darkorange" | "darkorchid" | "darkred" | "darksalmon" | "darkseagreen" | "darkslateblue" | "darkslategray" | "darkslategrey" | "darkturquoise" | "darkviolet" | "deeppink" | "deepskyblue" | "dimgray" | "dimgrey" | "dodgerblue" | "firebrick" | "floralwhite" | "forestgreen" | "fuchsia" | "gainsboro" | "ghostwhite" | "gold" | "goldenrod" | "gray" | "green" | "greenyellow" | "grey" | "honeydew" | "hotpink" | "indianred" | "indigo" | "ivory" | "khaki" | "lavender" | "lavenderblush" | "lawngreen" | "lemonchiffon" | "lightblue" | "lightcoral" | "lightcyan" | "lightgoldenrodyellow" | "lightgray" | "lightgreen" | "lightgrey" | "lightpink" | "lightsalmon" | "lightseagreen" | "lightskyblue" | "lightslategray" | "lightslategrey" | "lightsteelblue" | "lightyellow" | "lime" | "limegreen" | "linen" | "magenta" | "maroon" | "mediumaquamarine" | "mediumblue" | "mediumorchid" | "mediumpurple" | "mediumseagreen" | "mediumslateblue" | "mediumspringgreen" | "mediumturquoise" | "mediumvioletred" | "midnightblue" | "mintcream" | "mistyrose" | "moccasin" | "navajowhite" | "navy" | "oldlace" | "olive" | "olivedrab" | "orange" | "orangered" | "orchid" | "palegoldenrod" | "palegreen" | "paleturquoise" | "palevioletred" | "papayawhip" | "peachpuff" | "peru" | "pink" | "plum" | "powderblue" | "purple" | "rebeccapurple" | "red" | "rosybrown" | "royalblue" | "saddlebrown" | "salmon" | "sandybrown" | "seagreen" | "seashell" | "sienna" | "silver" | "skyblue" | "slateblue" | "slategray" | "slategrey" | "snow" | "springgreen" | "steelblue" | "tan" | "teal" | "thistle" | "tomato" | "transparent" | "turquoise" | "violet" | "wheat" | "white" | "whitesmoke" | "yellow" | "yellowgreen";
/**
* Returns the second argument if the first argument is `true` (defaults to `true`), otherwise returns the third argument (defaults to `false`)
* ```ts
* // valid
* type Case1 = If<true, 'valid'>
* // invalid
* type Case2 = If<false, 'valid', 'invalid'>
* ```
*/
type If<Condition,IfTrue=true,IfFalse=false>=Condition extends true ? IfTrue:IfFalse;
/**
* Returns a boolean if the passed type is `never`
* @example
* ```ts
* // true
* type Case1 = IsNever<never>
* // false
* type Case2 = IsNever<true>
* ```
*/
type IsNever<T>=[T] extends [never] ? true:false;
/**
* Returns the second argument if the first argument is `never` (defaults to `true`), otherwise returns the third argument (defaults to `false`)
* @example
* ```ts
* // 'valid'
* type Case1 = IfNever<never, 'valid'>
* // 'invalid'
* type Case2 = IfNever<never, 'valid', 'invalid'>
* ```
*/
type IfNever<T,IfTrue=true,IfFalse=false>=If<IsNever<T>,IfTrue,IfFalse>;type NeverifyPropertiesOptions={makeOptional:boolean;};
/**
* Turns all properties of an object to type `unknown`.
* If `makeOptional` option is `true`, makes all properties optional
* @example
* ```ts
* // {a:never; b:never}
* type Result = NeverifyProperties<{a: string; b: string}>
* ```
*/
type NeverifyProperties<T extends object,Options extends NeverifyPropertiesOptions={makeOptional:false;}>={[K in keyof T]:never;}extends infer Result ? If<Options["makeOptional"],Partial<Result>,Result>:never;
/**
* Returns the first argument if it is an empty array, otherwise returns `never`
* @example
* ```ts
* // never
* type Result = EmptyArray<[1]>
* ```
*/
type EmptyArray<T extends readonly unknown[]>=T extends readonly [unknown,...unknown[]] ? never:T;
/**
* Returns the first argument if it is a non empty array, otherwise returns `never`
* @example
* ```ts
* // never
* type Result = EmptyArray<[1]>
* ```
*/
type NonEmptyArray<T extends readonly unknown[]>=If<IsNever<EmptyArray<T>>,T,never>;
/**
* Returns a boolean whether the passed argument is an empty array
* @example
* ```ts
* // false
* type Result - IsEmptyArray<[1]>
*/
type IsEmptyArray<T extends readonly unknown[]>=If<IsNever<EmptyArray<T>>,false,true>;
/**
* Returns a boolean whether the passed argument is a non empty array
* @example
* ```ts
* // true
* type Result - IsEmptyArray<[1]>
*/
type IsNonEmptyArray<T extends readonly unknown[]>=If<IsNever<EmptyArray<T>>,true,false>;
/**
* Returns the second argument if the first argument is an empty array (defaults to `true`), otherwise returns the third argument (defaults to `false`)
* @example
* ```ts
* // string
* type Result = IfEmptyArray<[], string, number>
* ```
*/
type IfEmptyArray<T extends readonly unknown[],IfTrue=true,IfFalse=false>=If<IsEmptyArray<T>,IfTrue,IfFalse>;
/**
* Returns the second argument if the first argument is a non empty array (defaults to `true`), otherwise returns the third argument (defaults to `false`)
* @example
* ```ts
* // string
* type Result = IfEmptyArray<[1], string, number>
* ```
*/
type IfNonEmptyArray<T extends readonly unknown[],IfTrue=true,IfFalse=false>=If<IsNonEmptyArray<T>,IfTrue,IfFalse>;
/**
* Accepts a boolean and returns `true` if the passed type is `false`, otherwise returns `true`
* @example
* ```ts
* // false
* type Case1 = Not<true>
* // true
* type Case2 = Not<false>
* ```
*/
type Not<T extends boolean>=T extends true ? false:true;type PopOptions={includeRemoved:boolean;};
/**
* Removes last element from the first array argument.
* If the `includeRemoved` option is `true` return removed element with the new array in the format of [rest, removed]
* @example
* ```ts
* // [1, 2]
* type Case1 = Pop<[1, 2, 3]>
* // [[1, 2], 3]
* type Case2 = Pop<[1, 2, 3], {includeRemoved: true}>
* ```
*/
type Pop<T extends readonly unknown[],Options extends PopOptions={includeRemoved:false;}>=IsEmptyArray<T>extends true ? never:T extends readonly [...infer Rest extends readonly unknown[],infer Removed] ? If<Options["includeRemoved"],[Rest,Removed],Rest>:never;
/**
* Returns boolean whether the first argument extends the second argument
* @example
* ```ts
* // true
* type Case1 = Extends<1, number>
* // false
* type Case2 = Extends<number, 1>
* ```
*/
type Extends<T,Base>=[T] extends [Base] ? true:false;
/**
* Returns boolean whether the first argument doesn't extend the second argument
* @example
* ```ts
* // false
* type Case1 = Extends<1, number>
* // true
* type Case2 = Extends<number, 1>
* ```
*/
type NotExtends<T,Base>=Not<Extends<T,Base>>;
/**
* Returns the third argument if the first argument extends the second argument (defaults to `true`), otherwise returns the fourth argument (defaults to `false`)
* @example
* ```ts
* // 'valid'
* type Case1 = IfExtends<1, number, 'valid'>
* // 'invalid'
* type Case2 = IfExtends<1, string, 'valid', 'invalid'>
* ```
*/
type IfExtends<T,Base,IfTrue=true,IfFalse=false>=If<Extends<T,Base>,IfTrue,IfFalse>;
/**
* Returns the third argument if the first argument doesn't extend the second argument (defaults to `true`), otherwise returns the fourth argument (defaults to `false`)
* @example
* ```ts
* // 'valid'
* type Case1 = IfExtends<1, string, 'valid'>
* // 'invalid'
* type Case2 = IfExtends<1, number, 'valid', 'invalid'>
* ```
*/
type IfNotExtends<T,Base,IfTrue=true,IfFalse=false>=If<NotExtends<T,Base>,IfTrue,IfFalse>;
/**
* Returns boolean whether the every element of first array argument extend the second argument
* @example
* ```ts
* // true
* type Case1 = ExtendsArr<[1, 2, 3], number>
* // false
* type Case1 = ExtendsArr<[1, '2', 3], number>
* ```
*/
type ExtendsArr<T extends readonly unknown[],Base>=IsEmptyArray<T>extends true ? true:Pop<T,{includeRemoved:true;}>extends readonly [infer Rest extends readonly unknown[],infer Removed] ? Extends<Removed,Base>extends true ? ExtendsArr<Rest,Base>:false:false;
/**
* Returns result of logical multiplication of two params.
* @example
* ```ts
* // true
* type Case1 = And<true, true>
* // false
* type Case2 = And<false, true>
* ```
*/
type And<Condition1,Condition2>=IfExtends<Condition1,true,Extends<Condition2,true>>;
/**
* Returns result of logical multiplication of all elements inside the passed array type
* @example
* ```ts
* // true
* type Case1 = And<[true, true, true]>
* // false
* type Case2 = And<[true, true, false]>
* ```
*/
type AndArr<Conditions extends readonly unknown[]>=Extends<Conditions[number],true>;
/**
* Returns a boolean whether the passed argument is literal string
* @example
* ```ts
* // true
* type Case1 = IsStringLiteral<'a'>
* // false
* type Case2 = IsStringLiteral<string>
* ```
*/
type IsStringLiteral<T extends string>=string extends T ? false:true;
/**
* Returns the second argument if the first argument is `false` (defaults to `true`), otherwise returns the third argument (defaults to `false`)
* @example
* ```ts
* // valid
* type Case1 = IfNot<false, 'valid'>
* // invalid
* type Case2 = IfNot<false, 'valid', 'invalid'>
* ```
*/
type IfNot<Condition,IfTrue=true,IfFalse=false>=If<Condition,IfFalse,IfTrue>;type EmptyString<T extends string>="" extends T ? string extends T ? never:T:never;type NonEmptyString<T extends string>=string extends T ? string:If<IsNever<EmptyString<T>>,T,never>;type IsEmptyString<T extends string>=IfNot<IsNever<EmptyString<T>>>;type IsNonEmptyString<T extends string>=IfNot<IsNever<NonEmptyString<T>>>;type IfEmptyString<T extends string,IfTrue=true,IfFalse=false>=IfNot<IsNever<EmptyString<T>>,IfTrue,IfFalse>;type IfNonEmptyString<T extends string,IfTrue=true,IfFalse=false>=IfNot<IsNever<NonEmptyString<T>>,IfTrue,IfFalse>;type _AreAnagrams<Str1 extends string,Str2 extends string>=IsEmptyString<Str1>extends true ? IsEmptyString<Str2>extends true ? true:false:Str1 extends `${infer First extends string}${infer Rest1 extends string}` ? Str2 extends `${infer Prev extends string}${First}${infer Rest2 extends string}` ? _AreAnagrams<Rest1,`${Prev}${Rest2}`>:false:never;
/**
* Returns a boolean whether two passed string literals are anagrams
* @example
* ```ts
* // true
* type Case1 = AreAnagrams<"name", "eman">
* // false
* type Case1 = AreAnagrams<"name", "emand">
* ```
*/
type AreAnagrams<Str1 extends string,Str2 extends string>=And<IsStringLiteral<Str1>,IsStringLiteral<Str2>>extends true ? _AreAnagrams<Str1,Str2>:false;
/**
* Returns a boolean whether the passed type is `any`
* @example
* ```ts
* // true
* type Result = IsAny<any>
* ```
*/
type IsAny<T>=0 extends 1 & T ? true:false;
/**
* Returns the second argument if the first argument is `any` (defaults to `true`), otherwise returns the third argument (defaults to `false`)
* @example
* ```ts
* // string
* type Result = IfAny<any, string, number>
* ```
*/
type IfAny<T,IfTrue=true,IfFalse=false>=If<IsAny<T>,IfTrue,IfFalse>;type AnifyPropertiesOptions={makeOptional:boolean;};
/**
* Turns all properties of an object to type `any`.
* If `makeOptional` option is `true`, makes all properties optional
* @example
* ```ts
* // {a:any; b:any}
* type Result = AnifyProperties<{a: string; b: string}>
* ```
*/
type AnifyProperties<T extends object,Options extends AnifyPropertiesOptions={makeOptional:false;}>={[K in keyof T]:any;}extends infer Result ? If<Options["makeOptional"],Partial<Result>,Result>:never;
/**
* Returns the type of the element of the passed array argument
* @example
* ```ts
* // string
* type Case1 = ArrayElementType<string[]>
* // "a" | "b"
* type Case1 = ArrayElementType<readonly ("a" | "b")[]>
* ```
*/
type ArrayElementType<T extends readonly unknown[]>=T extends Readonly<Array<infer Item>>? Item:never;type LastCharacterOptions={includeRest:boolean;};type _LastCharacter<T extends string,Options extends LastCharacterOptions={includeRest:false;},Previous extends string="">=string extends T ? string:T extends `${infer First}${infer Rest}` ? IsEmptyString<Rest>extends true ? If<Options["includeRest"],[First,Previous],First>:_LastCharacter<Rest,Options,`${Previous}${First}`>:T;
/**
* Accepts a string argument and returns its first character.
* If the `includeRest` options is `true`, returns the first character and the rest of the string in the format of: [last, rest]
* @example
* ```ts
* // 'c'
* type Case1 = LastCharacter<'abc'>
* // ['c', 'ab']
* type Case2 = LastCharacter<'abc', {includeRest: true}>
* ```
*/
type LastCharacter<T extends string,Options extends LastCharacterOptions={includeRest:false;}>=_LastCharacter<T,Options>;type EvenDigit="0" | "2" | "4" | "6" | "8";type Integer<T extends number>=`${T}` extends `${string}.${string}` ? never:T;type Float<T extends number>=If<IsNever<Integer<T>>,T,never>;type Negative<T extends number>=`${T}` extends `-${string}` ? T:never;type Positive<T extends number>=If<IsNever<Negative<T>>,T,never>;type PositiveInteger<T extends number>=Positive<Integer<T>>;type NegativeInteger<T extends number>=Negative<Integer<T>>;type PositiveFloat<T extends number>=Positive<Float<T>>;type NegativeFloat<T extends number>=Negative<Float<T>>;type Even<T extends number>=IfNot<IsNever<Integer<T>>,`${T}` extends `${string}${EvenDigit}` ? T:never,never>;type Odd<T extends number>=IfNot<IsNever<Integer<T>>,If<IsNever<Even<T>>,T,never>,never>;type IsInteger<T extends number>=Not<IsNever<Integer<T>>>;type IsFloat<T extends number>=Not<IsNever<Float<T>>>;type IsEven<T extends number>=If<IsInteger<T>,`${T}` extends `${string}${EvenDigit}` ? true:false>;type IsOdd<T extends number>=If<IsInteger<T>,Not<IsEven<T>>>;type IsPositive<T extends number>=Not<IsNever<Positive<T>>>;type IsNegative<T extends number>=Not<IsNever<Negative<T>>>;type IsPositiveInteger<T extends number>=Not<IsNever<PositiveInteger<T>>>;type IsNegativeInteger<T extends number>=Not<IsNever<NegativeInteger<T>>>;type IsPositiveFloat<T extends number>=Not<IsNever<PositiveFloat<T>>>;type IsNegativeFloat<T extends number>=Not<IsNever<NegativeFloat<T>>>;type IfInteger<T extends number,IfTrue=true,IfFalse=false>=If<IsInteger<T>,IfTrue,IfFalse>;type IfFloat<T extends number,IfTrue=true,IfFalse=false>=If<IsFloat<T>,IfTrue,IfFalse>;type IfEven<T extends number,IfTrue=true,IfFalse=false>=If<IsEven<T>,IfTrue,IfFalse>;type IfOdd<T extends number,IfTrue=true,IfFalse=false>=If<IsOdd<T>,IfTrue,IfFalse>;type IfPositive<T extends number,IfTrue=true,IfFalse=false>=If<IsPositive<T>,IfTrue,IfFalse>;type IfNegative<T extends number,IfTrue=true,IfFalse=false>=If<IsNegative<T>,IfTrue,IfFalse>;type IfPositiveInteger<T extends number,IfTrue=true,IfFalse=false>=If<IsPositiveInteger<T>,IfTrue,IfFalse>;type IfNegativeInteger<T extends number,IfTrue=true,IfFalse=false>=If<IsNegativeInteger<T>,IfTrue,IfFalse>;type IfPositiveFloat<T extends number,IfTrue=true,IfFalse=false>=If<IsPositiveFloat<T>,IfTrue,IfFalse>;type IfNegativeFloat<T extends number,IfTrue=true,IfFalse=false>=If<IsNegativeFloat<T>,IfTrue,IfFalse>;type ParseNumber<T extends string | number>=T extends `${infer NumT extends number}` ? NumT:never;type Abs<T extends number>=`${T}` extends `-${infer PositiveT extends number}` ? PositiveT:T;type Negate<T extends number>=ParseNumber<`-${Abs<T>}`>;
/**
* Returns a boolean whether the first array argument is fixed length tuple
* @example
* ```ts
* // true
* type Case1 = IsTuple<[1, 2, 3]>
* // false
* type Case2 = IsTuple<number[]>
* ```
*/
type IsTuple<T extends readonly unknown[]>=NotExtends<number,T["length"]>;
/**
* Type version of `Array.prototype.join()`. Joins the first array argument by the second argument
* @example
* ```ts
* // 'a-p-p-l-e'
* type Case1 = Join<["a", "p", "p", "l", "e"], "-">
* // '21212'
* type Case2 = Join<["2", "2", "2"], 1>
* // 'o'
* type Case3 = Join<["o"], "u">
* ```
*/
type Join<T extends readonly(string | number)[],Glue extends string | number>=IsTuple<T>extends true ? T extends readonly [infer First extends string | number,...infer Rest extends readonly(string | number)[]] ? IfEmptyArray<Rest,First,`${First}${Glue}${Join<Rest,Glue>}`>:never:never;
/**
* Transform numbers, booleans, strings, bigints to string.
* ```ts
* // 'true'
* type Result = Stringify<true>
*
* ```
*/
type Stringify<T>=T extends number | boolean | string | bigint ? `${T}`:never;type DecrementMap=[-1,0,1,2,3,4,5,6,7,8];type NegativeCarryMap={"-1":9;};type _Decrement<Number extends string,Result extends string="">=Number extends "" ? ParseNumber<Result>:ParseNumber<LastCharacter<Number>>extends infer LastDigit extends number ? DecrementMap[LastDigit] extends infer Decremented extends number ? Number extends `${infer Rest}${LastDigit}` ? `${Decremented}` extends keyof NegativeCarryMap ? _Decrement<Rest,`${NegativeCarryMap[`${Decremented}`]}${Result}`>:`${Rest}${Decremented}${Result}` extends infer FinalResult extends string ? ParseNumber<FinalResult extends `0${infer FinalResultWithoutLeadingZero extends string}` ? FinalResultWithoutLeadingZero extends "" ? FinalResult:FinalResultWithoutLeadingZero:FinalResult>:never:never:never:never;type _DecrementNegativeOrZero<T extends number>=_Increment<Stringify<T>>extends infer PositiveDecrementResult extends number ? PositiveDecrementResult extends 0 ? PositiveDecrementResult:Negate<PositiveDecrementResult>:never;
/**
* Accepts an integer and returns the decremented value of it. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* // 5
* type Case1 = Decrement<6>
* // -7
* type Case2 = Decrement<-6>
* ```
*/
type Decrement<T extends number>=IsNegative<T>extends true ? _DecrementNegativeOrZero<Abs<T>>:T extends 0 ? _DecrementNegativeOrZero<T>:_Decrement<Stringify<T>>;type IncrementMap=[1,2,3,4,5,6,7,8,9,10];type LastDigitMap={10:0;};type _Increment<Number extends string,Result extends string="">=IsEmptyString<Number>extends true ? ParseNumber<`1${Result}`>:LastCharacter<Number>extends `${infer LastDigit extends number}` ? IncrementMap[LastDigit] extends infer Incremented extends number ? Number extends `${infer Rest}${LastDigit}` ? Incremented extends keyof LastDigitMap ? _Increment<Rest,`${LastDigitMap[Incremented]}${Result}`>:ParseNumber<`${Rest}${Incremented}${Result}`>:never:never:never;
/**
* Accepts an integer and returns the incremented value of it. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* // 2
* type Case1 = Increment<1>
* // -9
* type Case1 = Increment<-10>
* ```
*/
type Increment<T extends number>=IsNegative<T>extends true ? _Decrement<Stringify<Abs<T>>>extends infer NegativeIncrementResult extends number ? NegativeIncrementResult extends 0 ? NegativeIncrementResult:Negate<NegativeIncrementResult>:never:_Increment<Stringify<T>>;
/**
* Returns a tuple of whole and fraction part of the passed float number
* @example
* ```ts
* [12, 25]
* type Case1 = GetFloatNumberParts<12.25>
* [12, 25]
* type Case2 = GetFloatNumberParts<-12.25>
* ```
*/
type GetFloatNumberParts<T extends number>=IsFloat<T>extends true ? `${Abs<T>}` extends `${infer Whole extends number}.${infer Fraction extends number}` ? [Whole,Fraction]:never:never;
/**
* Type version of `Math.ceil()`. Returns ceiled value of the passed number
* @example
* ```ts
* // 2
* type Case1 = Ceil<1.2>
* // -1
* type Case2 = Ceil<-1.2>
* ```
*/
type Ceil<T extends number>=IsFloat<T>extends true ? GetFloatNumberParts<T>extends [infer Whole extends number,unknown] ? IsNegative<T>extends true ? Negate<Whole>:Increment<Whole>:never:T;
/**
* Returns a boolean whether the passed two arguments are equal
* @example
* ```ts
* // true
* type Case1 = IsEqual<string, string>
* // false
* type Case2 = IsEqual<1, 4>
* ```
*/
type IsEqual<T,U>=(<F>()=>F extends T ? 1:2)extends<F>()=>F extends U ? 1:2 ? true:false;
/**
* Returns a boolean whether the passed two arguments are not equal
* @example
* ```ts
* // true
* type Case1 = IsNotEqual<1, 4>
* // false
* type Case2 = IsNotEqual<string, string>
* ```
*/
type IsNotEqual<T,U>=Not<IsEqual<T,U>>;
/**
* Accepts two types and returns the third argument if the first two are equal (defaults to `true`), otherwise returns the fourth argument (defaults to `false`)
* @example
* ```ts
* // 'valid'
* type Case1 = IfEqual<string, string, 'valid'>
* // 'invalid'
* type Case1 = IfEqual<1, 4, 'valid', 'invalid'>
* ```
*/
type IfEqual<T,U,IfTrue=true,IfFalse=false>=If<IsEqual<T,U>,IfTrue,IfFalse>;
/**
* Accepts two types and returns the third argument if the first two are not equal (defaults to `true`), otherwise returns the fourth argument (defaults to `false`)
* @example
* ```ts
* // 'valid'
* type Case1 = IfNotEqual<1, 4, 'valid'>
* // 'invalid'
* type Case1 = IfNotEqual<string, string, 'valid', 'invalid'>
* ```
*/
type IfNotEqual<T,U,IfTrue=true,IfFalse=false>=If<IsNotEqual<T,U>,IfTrue,IfFalse>;
/**
* Accepts a string and removes leading characters specified in the second argument
* @example
* ```ts
* // 'bc'
* type Case1 = RemoveLeading<'aaabc', 'a'>
* // 'abc'
* type Case2 = RemoveLeading<'abc', 'd'>
* // ''
* type Case3 = RemoveLeading<'aaa', 'a'>
* // 'a'
* type Case3 = RemoveLeading<'aaa', 'aa'>
* ```
*/
type RemoveLeading<T extends string,Characters extends string>=T extends `${Characters}${infer Rest extends string}` ? IsEmptyString<Rest>extends true ? Rest:RemoveLeading<Rest,Characters>:T;type SubDecrementMap={"-9":-10;"-8":-9;"-7":-8;"-6":-7;"-5":-6;"-4":-5;"-3":-4;"-2":-3;"-1":-2;"0":-1;"1":0;"2":1;"3":2;"4":3;"5":4;"6":5;"7":6;"8":7;"9":8;};type SubNegativeCarryMap={"-10":0;"-9":1;"-8":2;"-7":3;"-6":4;"-5":5;"-4":6;"-3":7;"-2":8;"-1":9;};type SubMap={0:[0,-1,-2,-3,-4,-5,-6,-7,-8,-9];1:[1,0,-1,-2,-3,-4,-5,-6,-7,-8];2:[2,1,0,-1,-2,-3,-4,-5,-6,-7];3:[3,2,1,0,-1,-2,-3,-4,-5,-6];4:[4,3,2,1,0,-1,-2,-3,-4,-5];5:[5,4,3,2,1,0,-1,-2,-3,-4];6:[6,5,4,3,2,1,0,-1,-2,-3];7:[7,6,5,4,3,2,1,0,-1,-2];8:[8,7,6,5,4,3,2,1,0,-1];9:[9,8,7,6,5,4,3,2,1,0];};type _RemoveLeadingZeros<T extends string>=ParseNumber<RemoveLeading<T,"0">extends infer WithoutLeadingZeros extends string ? IfEmptyString<WithoutLeadingZeros,"0",WithoutLeadingZeros>:never>;type _Sub<Num1 extends string,Num2 extends string,NegativeCarry extends 0 | 1=0,Result extends string="">=IsEmptyString<Num2>extends true ? NegativeCarry extends 0 ? `${Num1}${Result}`:`${Decrement<ParseNumber<Num1>>}${Result}`:LastCharacter<Num1>extends `${infer Num1LastDigit extends keyof SubMap & number}` ? LastCharacter<Num2>extends `${infer Num2LastDigit extends keyof SubMap[Num1LastDigit] & number}` ? `${SubMap[Num1LastDigit][Num2LastDigit]}` extends infer DigitsSub extends keyof SubDecrementMap ?(NegativeCarry extends 1 ? Stringify<SubDecrementMap[DigitsSub]>:DigitsSub)extends infer DigitsSubWithCarry extends string ? Num1 extends `${infer Num1Rest}${Num1LastDigit}` ? Num2 extends `${infer Num2Rest}${Num2LastDigit}` ? DigitsSubWithCarry extends keyof SubNegativeCarryMap ? _Sub<Num1Rest,Num2Rest,1,`${SubNegativeCarryMap[DigitsSubWithCarry]}${Result}`>:_Sub<Num1Rest,Num2Rest,0,`${DigitsSubWithCarry}${Result}`>:never:never:never:never:never:never;
/**
* Accepts two integers and returns their subtraction. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* // 8
* type Case1 = Sub<10, 2>
* // -8
* type Case2 = Sub<2, 10>
* // 12
* type Case3 = Sub<2, -10>
* // -12
* type Case4 = Sub<-2, 10>
* ```
*/
type Sub<Num1 extends number,Num2 extends number>=IsNegativeInteger<Num1>extends true ? IsNegativeInteger<Num2>extends true ? IsLowerThan<Num1,Num2>extends true ? Negate<_RemoveLeadingZeros<_Sub<Stringify<Abs<Num1>>,Stringify<Abs<Num2>>>>>:_RemoveLeadingZeros<_Sub<Stringify<Abs<Num2>>,Stringify<Abs<Num1>>>>:Sum<Abs<Num1>,Num2>extends infer Result extends number ? Negate<Result>:never:IsNegativeInteger<Num2>extends true ? Sum<Num1,Abs<Num2>>:IsLowerThan<Num1,Num2>extends true ? Negate<_RemoveLeadingZeros<_Sub<Stringify<Num2>,Stringify<Num1>>>>:_RemoveLeadingZeros<_Sub<Stringify<Num1>,Stringify<Num2>>>;type SumIncrementMap=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19];type SumLastDigitMap={10:0;11:1;12:2;13:3;14:4;15:5;16:6;17:7;18:8;19:9;};type SumMap={0:[0,1,2,3,4,5,6,7,8,9];1:[1,2,3,4,5,6,7,8,9,10];2:[2,3,4,5,6,7,8,9,10,11];3:[3,4,5,6,7,8,9,10,11,12];4:[4,5,6,7,8,9,10,11,12,13];5:[5,6,7,8,9,10,11,12,13,14];6:[6,7,8,9,10,11,12,13,14,15];7:[7,8,9,10,11,12,13,14,15,16];8:[8,9,10,11,12,13,14,15,16,17];9:[9,10,11,12,13,14,15,16,17,18];};type _Sum<Num1 extends string,Num2 extends string,Carry extends 0 | 1=0,Result extends string="">=IsEmptyString<Num1>extends true ? Carry extends 0 ? ParseNumber<`${Num2}${Result}`>:_Increment<Num2,Result>:IsEmptyString<Num2>extends true ? Carry extends 0 ? ParseNumber<`${Num1}${Result}`>:_Increment<Num1,Result>:LastCharacter<Num1>extends `${infer Num1LastDigit extends keyof SumMap & number}` ? LastCharacter<Num2>extends `${infer Num2LastDigit extends keyof SumMap[Num1LastDigit] & number}` ? SumMap[Num1LastDigit][Num2LastDigit] extends infer DigitsSum extends number ?(Carry extends 1 ? SumIncrementMap[DigitsSum]:DigitsSum)extends infer DigitsSumWithCarry extends number ? Num1 extends `${infer Num1Rest}${Num1LastDigit}` ? Num2 extends `${infer Num2Rest}${Num2LastDigit}` ? DigitsSumWithCarry extends keyof SumLastDigitMap ? _Sum<Num1Rest,Num2Rest,1,`${SumLastDigitMap[DigitsSumWithCarry]}${Result}`>:_Sum<Num1Rest,Num2Rest,0,`${DigitsSumWithCarry}${Result}`>:never:never:never:never:never:never;
/**
* Accepts two integers and returns their sum. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* // 13
* type Case1 = Sum<4, 9>
* // 5
* type Case2 = Sum<-4, 9>
* // -5
* type Case3 = Sum<4, -9>
* // -13
* type Case4 = Sum<-4, -9>
* ```
*/
type Sum<Num1 extends number,Num2 extends number>=IsNegativeInteger<Num1>extends true ? IsNegativeInteger<Num2>extends true ? Negate<_Sum<Stringify<Abs<Num1>>,Stringify<Abs<Num2>>>>:Sub<Num2,Abs<Num1>>:IsNegativeInteger<Num2>extends true ? Sub<Num1,Abs<Num2>>:_Sum<Stringify<Num1>,Stringify<Num2>>;type _SumArr<T extends readonly number[],CurrentSum extends number=0>=IsEmptyArray<T>extends true ? CurrentSum:Pop<T,{includeRemoved:true;}>extends infer PopResult ? IsNever<PopResult>extends true ? CurrentSum:PopResult extends [infer Rest extends number[],infer Num1 extends number] ? _SumArr<Rest,Sum<CurrentSum,Num1>>:never:CurrentSum;
/**
* Accepts an array of integers and returns the sum of its elements. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* // 10
* type Case1 = SumArr<[1, 2, 3, 4]>
* // 2
* type Case2 = SumArr<[1, 2, 3, -4]>
* ```
*/
type SumArr<T extends readonly number[]>=IsTuple<T>extends true ? _SumArr<T>:never;type _StringLength<S extends string,Parts extends [string[],string[],string[],string[]]=[[],[],[],[]]>=S extends "" ? Sum<Sum<Parts[0]["length"],Parts[1]["length"]>,Sum<Parts[2]["length"],Parts[3]["length"]>>:S extends `${infer C1 extends string}${infer Rest1 extends string}` ? Rest1 extends `${infer C2 extends string}${infer Rest2 extends string}` ? Rest2 extends `${infer C3 extends string}${infer Rest3 extends string}` ? Rest3 extends `${infer C4 extends string}${infer Rest4 extends string}` ? _StringLength<Rest4,[[...Parts[0],C1],[...Parts[1],C2],[...Parts[2],C3],[...Parts[3],C4]]>:_StringLength<Rest3,[[...Parts[0],C1],[...Parts[1],C2],[...Parts[2],C3],Parts[3]]>:_StringLength<Rest2,[[...Parts[0],C1],[...Parts[1],C2],Parts[2],Parts[3]]>:_StringLength<Rest1,[[...Parts[0],C1],Parts[1],Parts[2],Parts[3]]>:_StringLength<S,Parts>;
/**
* Returns the length of the passed string. Range of string length `[0, 3968]`
* @example
* ```ts
* // 0
* type Case1 = StringLength<''>
* // 3
* type Case2 = StringLength<'xxx'>
* ```
*/
type StringLength<S extends string>=_StringLength<S>;
/**
* Accepts two strings, returns the third argument (defaults to `never`) if the first string is shorter, otherwise returns the fourth argument (defaults to `never`) if the second argument is shorter, if strings have the same length returns the fifth argument (defaults to `never`)
* @example
* ```ts
* // 'first shorter'
* type Case1 = CompareStringLength<'a', 'ab', 'first shorter'>
* // 'first longer'
* type Case2 = CompareStringLength<'abc', 'ab', 'first shorter', 'first longer'>
* // 'equal'
* type Case3 = CompareStringLength<'ab', 'ab', 'first shorter', 'first longer', 'equal'>
* ```
*/
type CompareStringLength<Str1 extends string,Str2 extends string,IfStr1Shorter=never,IfStr2Shorter=never,IfEqual=never>=IsEmptyString<Str1>extends true ? IsEmptyString<Str2>extends true ? IfEqual:IfStr1Shorter:IsEmptyString<Str2>extends true ? IfStr2Shorter:Str1 extends `${string}${infer Str1Rest extends string}` ? Str2 extends `${string}${infer Str2Rest extends string}` ? CompareStringLength<Str1Rest,Str2Rest,IfStr1Shorter,IfStr2Shorter,IfEqual>:never:never;
/**
* Accepts two strings, returns a boolean whether the first string is shorter
* @example
* ```ts
* // true
* type Case1 = IsShorterString<'a', 'ab'>
* // false
* type Case2 = IsShorterString<'abc', 'ab'>
* ```
*/
type IsShorterString<Str1 extends string,Str2 extends string>=CompareStringLength<Str1,Str2,true,false,false>;
/**
* Accepts two strings, returns a boolean whether the first string is longer
* @example
* ```ts
* // true
* type Case1 = IsLongerString<'ab', 'a'>
* // false
* type Case2 = IsLongerString<'a', 'ab'>
* ```
*/
type IsLongerString<Str1 extends string,Str2 extends string>=CompareStringLength<Str1,Str2,false,true,false>;
/**
* Accepts two strings, returns a boolean whether strings have the same length
* @example
* ```ts
* // true
* type Case1 = IsSameLengthString<'ab', 'ab'>
* // false
* type Case2 = IsSameLengthString<'ab', 'abc'>
* ```
*/
type IsSameLengthString<Str1 extends string,Str2 extends string>=CompareStringLength<Str1,Str2,false,false,true>;
/**
* Returns number of digits of the passed number
* @example
* ```ts
* // 3
* type Case1 = NumberLength<100>
* // 15
* type Case2 = NumberLength<100000000000000>
* ```
*/
type NumberLength<T extends number>=StringLength<Stringify<T>>;
/**
* Accepts two numbers, returns the third argument (defaults to `never`) if the first number is shorter, otherwise returns the fourth argument (defaults to `never`) if the second argument is shorter, if numbers have the same length returns the fifth argument (defaults to `never`)
* @example
* ```ts
* // 'first shorter'
* type Case1 = CompareNumberLength<1, 12, 'first shorter'>
* // 'first longer'
* type Case2 = CompareNumberLength<123, 12, 'first shorter', 'first longer'>
* // 'equal'
* type Case3 = CompareNumberLength<12, 12, 'first shorter', 'first longer', 'equal'>
* ```
*/
type CompareNumberLength<Num1 extends number,Num2 extends number,IfNum1Shorter=never,IfNum2Shorter=never,IfEqual=never>=CompareStringLength<Stringify<Num1>,Stringify<Num2>,IfNum1Shorter,IfNum2Shorter,IfEqual>;
/**
* Accepts two numbers, returns a boolean whether the first number is shorter
* @example
* ```ts
* // true
* type Case1 = IsShorterNumber<1, 10>
* // false
* type Case2 = IsShorterNumber<100, 10>
* ```
*/
type IsShorterNumber<Num1 extends number,Num2 extends number>=CompareNumberLength<Num1,Num2,true,false,false>;
/**
* Accepts two numbers, returns a boolean whether the first number is longer
* @example
* ```ts
* // true
* type Case1 = IsLongerNumber<10, 1>
* // false
* type Case2 = IsLongerNumber<10, 100>
* ```
*/
type IsLongerNumber<Num1 extends number,Num2 extends number>=CompareNumberLength<Num1,Num2,false,true,false>;
/**
* Accepts two numbers, returns a boolean whether numbers have the same length
* @example
* ```ts
* // true
* type Case1 = IsSameLengthNumber<10, 10>
* // false
* type Case2 = IsSameLengthNumber<10, 100>
* ```
*/
type IsSameLengthNumber<Num1 extends number,Num2 extends number>=CompareNumberLength<Num1,Num2,false,false,true>;type LowerThanMap={"0":["1","2","3","4","5","6","7","8","9"];"1":["2","3","4","5","6","7","8","9"];"2":["3","4","5","6","7","8","9"];"3":["4","5","6","7","8","9"];"4":["5","6","7","8","9"];"5":["6","7","8","9"];"6":["7","8","9"];"7":["8","9"];"8":["9"];"9":[];};type _IsLowerThan<Num1 extends string,Num2 extends string>=Num1 extends `${infer Num1Character extends keyof LowerThanMap}${infer Num1Rest extends string}` ? Num2 extends `${infer Num2Character extends string}${infer Num2Rest extends string}` ? IsEqual<Num1Character,Num2Character>extends true ? _IsLowerThan<Num1Rest,Num2Rest>:Num2Character extends LowerThanMap[Num1Character][number] ? true:false:true:false;
/**
* Returns a boolean whether the first passed integer is lower than the second integer. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* // true
* type Case1 = IsLowerThan<1, 10>
* // false
* type Case2 = IsLowerThan<1, -10>
* ```
*/
type IsLowerThan<Num1 extends number,Num2 extends number>=IsEqual<Num1,Num2>extends true ? false:IsNegative<Num1>extends true ? IsNegative<Num2>extends false ? true:CompareNumberLength<Num1,Num2,false,true,Not<_IsLowerThan<Stringify<Abs<Num1>>,Stringify<Abs<Num2>>>>>:IsNegative<Num2>extends true ? false:CompareNumberLength<Num1,Num2,true,false,_IsLowerThan<Stringify<Abs<Num1>>,Stringify<Abs<Num2>>>>;
/**
* Returns a boolean whether the first passed integer is lower than the second integer. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* // 'valid'
* type Case1 = IfLowerThan<1, 10, 'valid'>
* // 'invalid'
* type Case2 = IfLowerThan<1, -10, 'valid', 'invalid'>
* ```
*/
type IfLowerThan<Num1 extends number,Num2 extends number,IfTrue=true,IfFalse=false>=If<IsLowerThan<Num1,Num2>,IfTrue,IfFalse>;type IsLowerOrEqual<Num1 extends number,Num2 extends number>=IsEqual<Num1,Num2>extends true ? true:IsLowerThan<Num1,Num2>;
/**
* Returns a boolean whether the first passed integer is greater than the second integer. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* // true
* type Case1 = IsGreaterThan<10, 1>
* // false
* type Case2 = IsGreaterThan<-10, 1>
* ```
*/
type IsGreaterThan<Num1 extends number,Num2 extends number>=IsLowerThan<Num2,Num1>;
/**
* Returns the third argument if the first argument (integer) is greater than the second argument (integer) (defaults to `true`), otherwise returns the fourth argument (defaults to `false`). Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* 'valid'
* type Case1 = IfGreaterThan<10, 1, 'valid'>
* // 'invalid'
* type Case2 = IfGreaterThan<-10, 1, 'valid', 'invalid'>
* ```
*/
type IfGreaterThan<Num1 extends number,Num2 extends number,IfTrue=true,IfFalse=false>=IfLowerThan<Num2,Num1,IfTrue,IfFalse>;
/**
* Returns a boolean whether the first passed integer is greater than the second integer or equal. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* // true
* type Case1 = IsGreaterThan<10, 1>
* // false
* type Case2 = IsGreaterThan<-10, 1>
* // true
* type Case3 = IsGreaterThan<10, 10>
* ```
*/
type IsGreaterOrEqual<Num1 extends number,Num2 extends number>=IsEqual<Num1,Num2>extends true ? true:IsGreaterThan<Num1,Num2>;
/**
* Returns the third argument if the first argument (integer) is greater than the second argument (integer) or equal (defaults to `true`), otherwise returns the fourth argument (defaults to `false`). Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* 'valid'
* type Case1 = IfGreaterThan<10, 1, 'valid'>
* // 'invalid'
* type Case2 = IfGreaterThan<-10, 1, 'valid', 'invalid'>
* ```
*/
type IfGreaterOrEqual<Num1 extends number,Num2 extends number,IfTrue=true,IfFalse=false>=If<IsEqual<Num1,Num2>extends true ? true:IsGreaterThan<Num1,Num2>,IfTrue,IfFalse>;type IsBetweenOptions={minIncluded?:boolean;maxIncluded?:boolean;};
/**
* Returns a boolean whether the first integer argument is between the second and the third integer argument
* By default borders of the interval are included, which can be modified by the second argument.
* `minIncluded`, `maxIncluded` options show whether to include the lower and the higher borders respectively. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`
* @example
* ```ts
* // true
* type Case1 = IsBetween<1, 1, 10>
* // false
* type Case2 = IsBetween<1, 1, 10, {minIncluded: false}>
* // false
* type Case3 = IsBetween<10, 1, 10, {maxIncluded: false}>
* ```
*/
type IsBetween<Num extends number,Min extends number,Max extends number,Options extends IsBetweenOptions={minIncluded:true;maxIncluded:true;}>=IsEqual<Num,Min>extends true ? Options["minIncluded"]:IsEqual<Num,Max>extends true ? Options["maxIncluded"]:And<IsGreaterThan<Num,Min>,IsLowerThan<Num,Max>>;
/**
* Type version of `String.prototype.split()`. Splits the first string argument by the second string argument
* @example
* ```ts
* // ['a', 'b', 'c']
* type Case1 = Split<'abc', ''>
* // ['a', 'b', 'c']
* type Case2 = Split<'a,b,c', ','>
* ```
*/
type Split<Str extends string,Del extends string | number>=string extends Str ? string[]:"" extends Str ? []:Str extends `${infer T}${Del}${infer U}` ? [T,...Split<U,Del>]:[Str];type _IsValidRGBParameter<T extends number>=IsInteger<T>extends true ? IsBetween<T,0,255>:false;type RGBOptions={separator:string;};type DefaultRGBOptions={separator:",";};
/**
* Returns the first string argument if it is a valid RGB color, otherwise returns `never`.
* The second argument is an object type with `separator: string` property, which shows the separator between color parameters (defaults to `', '`)
* @example
* ```ts
* // rgb(23, 242, 0)
* type Case1 = RGB<'rgb(23, 242, 0)'>
* // never
* type Case2 = RGB<'rgb(324, 123, 3)'>
* // rgb(23,242,0)
* type Case3 = RGB<'rgb(23,242,0)', { separator: ',' }>
* ```
*/
type RGB<T extends string,Options extends RGBOptions=DefaultRGBOptions>=T extends `rgb(${infer R extends number}${Options["separator"]}${infer G extends number}${Options["separator"]}${infer B extends number})` ? AndArr<[_IsValidRGBParameter<R>,_IsValidRGBParameter<G>,_IsValidRGBParameter<B>]>extends true ? T:never:never;
/**
* Returns a boolean whether the first string argument is a valid RGB color.
* The second argument is an object type with `separator: string` property, which shows the separator between color parameters (defaults to `', '`)
* @example
* ```ts
* // true
* type Case1 = IsRGB<'rgb(23, 242, 0)'>
* // false
* type Case2 = IsRGB<'rgb(324, 123, 3)'>
* // true
* type Case3 = IsRGB<'rgb(23,242,0)', { separator: ',' }>
* ```
*/
type IsRGB<T extends string,Options extends RGBOptions=DefaultRGBOptions>=Not<IsNever<RGB<T,Options>>>;
/**
* Returns the third argument if the first argument is valid RGB color (defaults to `true`), otherwise returns the fourth argument (defaults to `false`)
* The second argument is an object type with `separator: string` property, which shows the separator between color parameters (defaults to `', '`)
* @example
* ```ts
* // 'true'
* type Case1 = IfRGB<'rgb(23, 242, 0)', 'true'>
* // 'invalid'
* type Case2 = IfRGB<'rgb(324, 123, 3)', 'valid', 'invalid'>
* // true
* type Case3 = IfRGB<'rgb(23,242,0)', { separator: ',' }>
* ```
*/
type IfRGB<T extends string,Options extends RGBOptions=DefaultRGBOptions,IfTrue=true,IfFalse=false>=If<IsRGB<T,Options>,IfTrue,IfFalse>;type _ValidHEXCharacters=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"];type _AllowedHEXLength=3 | 4 | 6 | 8;
/**
* Returns the first string argument if it is a valid HEX color, otherwise returns `never`
* @example
* // '#000'
* type Case1 = HEX<'#000'>
* // never
* type Case2 = HEX<'#g00'>
* // '#0000'
* type Case3 = HEX<'#0000'>
* // never
* type Case4 = HEX<'#00000'>
* // '#000000'
* type Case5 = HEX<'#000000'>
* // '#00000000'
* type Case6 = HEX<'#00000000'>
*/
type HEX<T extends string>=(Uppercase<T>extends `#${infer HEXWithoutHashTag extends string}` ? StringLength<HEXWithoutHashTag>extends _AllowedHEXLength ? ExtendsArr<Split<HEXWithoutHashTag,"">,_ValidHEXCharacters[number]>:false:false)extends true ? T:never;
/**
* Returns a boolean whether the first string argument is a valid HEX color.
* @example
* ```ts
* // true
* type Case1 = IsHEX<'#000'>
* // false
* type Case2 = IsHEX<'#g00'>
* ```
*/
type IsHEX<T extends string>=Not<IsNever<HEX<T>>>;
/**
* Returns the second argument if the first argument is valid HEX color (defaults to `true`), otherwise returns the third argument (defaults to `false`)
* @example
* ```ts
* // true
* type Case1 = IfHEX<'#000'>
* // false
* type Case2 = IfHEX<'#g00'>
* // 'valid'
* type Case3 = IfHEX<'#0000', 'valid'>
* // 'invalid'
* type Case4 = IfHEX<'#00000', 'valid', 'invalid'>
* ```
*/
type IfHEX<T extends string,IfTrue=true,IfFalse=false>=If<IsHEX<T>,IfTrue,IfFalse>;type HSLOptions={separator:string;};type DefaultHSLOptions={separator:",";};
/**
* Returns the first string argument if it is a valid HSL color, otherwise returns `never`.
* The second argument is an object type with `separator: string` property, which shows the separator between color parameters (defaults to `', '`)
* @example
* ```ts
* // hsl(100, 34%, 56%)
* type Case1 = HSL<'hsl(100, 34%, 56%)'>
* // never
* type Case2 = HSL<'hsl(100, 200%, 3)'>
* // hsl(100,34%,56%)
* type Case3 = HSL<'hsl(100,34%,56%)', { separator: ',' }>
* ```
*/
type HSL<T extends string,Options extends HSLOptions=DefaultHSLOptions>=(T extends `hsl(${infer H extends number}${Options["separator"]}${infer S extends number}%${Options["separator"]}${infer L extends number}%)` ? AndArr<[IsInteger<H>,IsInteger<S>,IsInteger<L>]>extends true ? AndArr<[IsBetween<S,0,100>,IsBetween<L,0,100>]>:false:false)extends true ? T:never;
/**
* Returns a boolean whether the first string argument is a valid HSL color.
* The second argument is an object type with `separator: string` property, which shows the separator between color parameters (defaults to `', '`)
* @example
* ```ts
* // true
* type Case1 = IsHSL<'hsl(100, 34%, 56%)'>
* // false
* type Case2 = IsHSL<'hsl(101, 200%, 3)'>
* // true
* type Case3 = IsHSL<'hsl(100,34%,56%)', { separator: ',' }>
* ```
*/
type IsHSL<T extends string,Options extends HSLOptions=DefaultHSLOptions>=Not<IsNever<HSL<T,Options>>>;
/**
* Returns the third argument if the first argument is valid HSL color (defaults to `true`), otherwise returns the fourth argument (defaults to `false`)
* The second argument is an object type with `separator: string` property, which shows the separator between color parameters (defaults to `', '`)
* @example
* ```ts
* // 'true'
* type Case1 = IfHSL<'hsl(100, 34%, 56%)', 'true'>
* // 'invalid'
* type Case2 = IfHSL<'hsl(101, 200%, 3)', 'valid', 'invalid'>
* // true
* type Case3 = IfHSL<'hsl(100,34%,56%)', { separator: ',' }>
* ```
*/
type IfHSL<T extends string,Options extends HSLOptions=DefaultHSLOptions,IfTrue=true,IfFalse=false>=If<IsHSL<T,Options>,IfTrue,IfFalse>;type ColorOptions={rgbOptions?:RGBOptions;hslOptions?:HSLOptions;};type DefaultColorOptions={rgbOptions:DefaultRGBOptions;hslOptions:DefaultHSLOptions;};
/**
* Returns the first string argument if it is a valid RGB or HEX or HSL color, otherwise returns `never`.
* The second argument is an object type with `rgbOptions: RGBOptions` and `hslOptions: hslOptions` properties, which can accept the separator between color parameters (defaults to `', '`)
* @example
* ```ts
* // rgb(23, 242, 0)
* type Case1 = Color<'rgb(23, 242, 0)'>
* // never
* type Case2 = Color<'rgb(324, 123, 3)'>
* // '#000000'
* type Case3 = HEX<'#000000'>
* // 'hsl(100,34%,56%)'
* type Case4 = Color<'hsl(100,34%,56%)', { hslOptions: { separator: ',' } }>
* ```
*/
type Color<T extends string,Options extends ColorOptions=DefaultColorOptions>=RGB<T,Options["rgbOptions"]>| HEX<T>| HSL<T,Options["hslOptions"]>;
/**
* Returns a boolean whether the first string argument is a valid RGB or HEX or HSL color.
* The second argument is an object type with `rgbOptions: RGBOptions` and `hslOptions: hslOptions` properties, which can accept the separator between color parameters (defaults to `', '`)
* @example
* ```ts
* // true
* type Case1 = Color<'rgb(23, 242, 0)'>
* // false
* type Case2 = Color<'rgb(324, 123, 3)'>
* // true
* type Case3 = HEX<'#000000'>
* // true
* type Case4 = Color<'hsl(100,34%,56%)', { hslOptions: { separator: ',' } }>
* ```
*/
type IsColor<T extends string,Options extends ColorOptions=DefaultColorOptions>=Not<IsNever<Color<T,Options>>>;
/**
* Returns the third argument if the first argument is valid RGB or HEX or HSL color (defaults to `true`), otherwise returns the fourth argument (defaults to `false`)
* The second argument is an object type with `rgbOptions: RGBOptions` and `hslOptions: hslOptions` properties, which can accept the separator between color parameters (defaults to `', '`)
* @example
* ```ts
* // 'valid'
* type Case1 = Color<'rgb(23, 242, 0)', 'valid'>
* // 'invalid'
* type Case2 = Color<'rgb(324, 123, 3)', 'valid', 'invalid'>
* // true
* type Case3 = Color<'#000000'>
* ```
*/
type IfColor<T extends string,Options extends ColorOptions=DefaultColorOptions,IfTrue=true,IfFalse=false>=If<IsColor<T,Options>,IfTrue,IfFalse>;
/**
* Type version of `Array.prototype.concat()`. Concatenates two arrays into one.
* @example
* ```ts
* // [number, number, string, string]
* type Result = Concat<[number, number], [string, string]>
* ```
*/
type Concat<T extends readonly unknown[],U>=[...T,...(U extends readonly unknown[] ? U:[U])];
/**
* Accepts an integer argument and returns a tuple of its digits
* @example
* ```ts
* // [1]
* type Case1 = DigitsTuple<1>
* // [1, 2, 3]
* type Case2 = DigitsTuple<123>
* // [1, 2, 3]
* type Case3 = DigitsTuple<-123>
* ```
*/
type DigitsTuple<T extends number>=number extends T ? number[]:Split<Stringify<Abs<T>>,"">extends infer Result ?{[K in keyof Result]:Result[K] extends string ? ParseNumber<Result[K]>:Result[K];}:never;
/**
* Pushes the second argument to the first array argument
* @example
* ```ts
* // [1, 2, 3, 4, 5]
* type Case1 = Push<[1, 2, 3, 4], 5>
* ```
*/
type Push<T extends readonly unknown[],U extends unknown>=[...T,U];type _Repeat<T extends string,Count extends number,Result extends string="",Iteration extends unknown[]=[]>=Iteration["length"] extends Count ? Result:_Repeat<T,Count,`${T}${Result}`,Push<Iteration,unknown>>;
/**
* Repeats the first argument number of times specified in the second argument. Range `[0,999]`
* @example
* ```ts
* // 'x'
* type Case1 = Repeat<'x', 1>
* // 'xxxxx'
* type Case2 = Repeat<'x', 5>
* ```
*/
type Repeat<T extends string,Count extends number>=_Repeat<T,Count>;
/**
* Returns the first argument if it extends the second argument, returns the third argument otherwise
* @example
* ```ts
* // 1
* type Case1 = ReturnItselfIfExtends<1, number, 2>
* // 2
* type Case2 = ReturnItselfIfExtends<'1', number, 2>
* ```
*/
type ReturnItselfIfExtends<T,Base,Else>=T extends Base ? T:Else;
/**
* Returns the first argument if it doesn't extend the second argument, returns the third argument otherwise
* @example
* ```ts
* // '1'
* type Case1 = ReturnItselfIfNotExtends<'1', number, 2>
* // 2
* type Case2 = ReturnItselfIfNotExtends<1, number, 2>
* ```
*/
type ReturnItselfIfNotExtends<T,Base,Else>=T extends Base ? Else:T;type MultiplicationMap={0:[0,0,0,0,0,0,0,0,0,0];1:[0,1,2,3,4,5,6,7,8,9];2:[0,2,4,6,8,10,12,14,16,18];3:[0,3,6,9,12,15,18,21,24,27];4:[0,4,8,12,16,20,24,28,32,36];5:[0,5,10,15,20,25,30,35,40,45];6:[0,6,12,18,24,30,36,42,48,54];7:[0,7,14,21,28,35,42,49,56,63];8:[0,8,16,24,32,40,48,56,64,72];9:[0,9,18,27,36,45,54,63,72,81];};type _MultSingle<Num1 extends string,DigitOfNum2 extends keyof MultiplicationMap,Carry extends number=0,Result extends string="">=IsEmptyString<Num1>extends true ? ReturnItselfIfNotExtends<RemoveLeading<`${Carry}${Result}`,"0">,"","0">:IsEqual<Num1,0>extends true ? "0":IsEqual<DigitOfNum2,0>extends true ? "0":LastCharacter<Num1,{includeRest:true;}>extends [infer Num1LastCharacter extends string,infer Num1Rest extends string] ? Stringify<Sum<MultiplicationMap[DigitOfNum2][ParseNumber<Num1LastCharacter>& keyof MultiplicationMap[DigitOfNum2]],Carry>>extends infer Multiplied extends string ? LastCharacter<Multiplied,{includeRest:true;}>extends [infer MultipliedLastDigit extends string,infer MultipliedRest extends string] ? _MultSingle<Num1Rest,DigitOfNum2,If<IsNever<ParseNumber<MultipliedRest>>,0,ParseNumber<MultipliedRest>>,`${MultipliedLastDigit}${Result}`>:never:never:never;type _Mult<Num1 extends string,Num2 extends string,Result extends string="",Iteration extends unknown[]=[]>=IsEmptyString<Num2>extends true ? Result:LastCharacter<Num2,{includeRest:true;}>extends [infer Num2LastCharacter extends string,infer Num2Rest extends string] ? ParseNumber<Num2LastCharacter>extends infer Num2Digit extends keyof MultiplicationMap ? _Mult<Num1,Num2Rest,Stringify<_Sum<Result,ReturnItselfIfNotExtends<Remov