UNPKG

@storm-stack/types

Version:

⚡ The storm-stack monorepo contains utility applications, tools, and various libraries to create modern and scalable web applications.

153 lines (152 loc) 7.31 kB
import { BuildTuple, IsEqual } from "./base"; import { IsNegative, NegativeInfinity, PositiveInfinity } from "./number"; import { StringLength, StringToNumber } from "./string"; /** * Returns a boolean for whether A is false. * * @example * ``` * Not<true>; * //=> false * * Not<false>; * //=> true * ``` */ export type Not<A extends boolean> = A extends true ? false : A extends false ? true : never; /** * Returns a boolean for whether the given `boolean` is not `false`. */ export type IsNotFalse<T extends boolean> = [T] extends [false] ? false : true; export type Or<A extends boolean, B extends boolean> = [ A, B ][number] extends false ? false : true extends [IsEqual<A, true>, IsEqual<B, true>][number] ? true : never; export type And<A extends boolean, B extends boolean> = [ A, B ][number] extends true ? true : true extends [IsEqual<A, false>, IsEqual<B, false>][number] ? false : never; /** * Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both positive numeric characters. * * @example * ``` * PositiveNumericCharacterGt<'5', '1'>; * //=> true * * PositiveNumericCharacterGt<'1', '1'>; * //=> false * ``` */ export type PositiveNumericCharacterGt<A extends string, B extends string> = NumericString extends `${infer HeadA}${A}${infer TailA}` ? NumericString extends `${infer HeadB}${B}${infer TailB}` ? HeadA extends `${HeadB}${infer _}${infer __}` ? true : false : never : never; /** * Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both numeric strings and have the same length. * * @example * ``` * SameLengthPositiveNumericStringGt<'50', '10'>; * //=> true * * SameLengthPositiveNumericStringGt<'10', '10'>; * //=> false * ``` */ export type SameLengthPositiveNumericStringGt<A extends string, B extends string> = A extends `${infer FirstA}${infer RestA}` ? B extends `${infer FirstB}${infer RestB}` ? FirstA extends FirstB ? SameLengthPositiveNumericStringGt<RestA, RestB> : PositiveNumericCharacterGt<FirstA, FirstB> : never : false; type NumericString = "0123456789"; /** * Returns a boolean for whether `A` is greater than `B`, where `A` and `B` are both positive numeric strings. * * @example * ``` * PositiveNumericStringGt<'500', '1'>; * //=> true * * PositiveNumericStringGt<'1', '1'>; * //=> false * * PositiveNumericStringGt<'1', '500'>; * //=> false * ``` */ export type PositiveNumericStringGt<A extends string, B extends string> = A extends B ? false : [ BuildTuple<StringLength<A>, 0>, BuildTuple<StringLength<B>, 0> ] extends infer R extends [readonly unknown[], readonly unknown[]] ? R[0] extends [...R[1], ...infer Remain extends readonly unknown[]] ? 0 extends Remain["length"] ? SameLengthPositiveNumericStringGt<A, B> : true : false : never; export type LessThan<A extends number, B extends number> = number extends A | B ? never : GreaterThanOrEqual<A, B> extends true ? false : true; export type GreaterThan<A extends number, B extends number> = number extends A | B ? never : [ IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>, IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity> ] extends infer R extends [boolean, boolean, boolean, boolean] ? Or<And<IsEqual<R[0], true>, IsEqual<R[2], false>>, And<IsEqual<R[3], true>, IsEqual<R[1], false>>> extends true ? true : Or<And<IsEqual<R[1], true>, IsEqual<R[3], false>>, And<IsEqual<R[2], true>, IsEqual<R[0], false>>> extends true ? false : true extends R[number] ? false : [IsNegative<A>, IsNegative<B>] extends infer R extends [ boolean, boolean ] ? [true, false] extends R ? false : [false, true] extends R ? true : [false, false] extends R ? PositiveNumericStringGt<`${A}`, `${B}`> : PositiveNumericStringGt<`${NumberAbsolute<B>}`, `${NumberAbsolute<A>}`> : never : never; export type GreaterThanOrEqual<A extends number, B extends number> = number extends A | B ? never : A extends B ? true : GreaterThan<A, B>; /** * Returns the minimum value from a tuple of integers. * * Note: * - Float numbers are not supported. * * @example * ``` * ArrayMin<[1, 2, 5, 3]>; * //=> 1 * * ArrayMin<[1, 2, 5, 3, -5]>; * //=> -5 * ``` */ export type ArrayMin<A extends number[], Result extends number = PositiveInfinity> = number extends A[number] ? never : A extends [infer F extends number, ...infer R extends number[]] ? LessThan<F, Result> extends true ? ArrayMin<R, F> : ArrayMin<R, Result> : Result; /** * Returns the maximum value from a tuple of integers. * * Note: * - Float numbers are not supported. * * @example * ``` * ArrayMax<[1, 2, 5, 3]>; * //=> 5 * * ArrayMax<[1, 2, 5, 3, 99, -1]>; * //=> 99 * ``` */ export type ArrayMax<A extends number[], Result extends number = NegativeInfinity> = number extends A[number] ? never : A extends [infer F extends number, ...infer R extends number[]] ? GreaterThan<F, Result> extends true ? ArrayMax<R, F> : ArrayMax<R, Result> : Result; /** * Returns the absolute value of a given value. * * @example * ``` * NumberAbsolute<-1>; * //=> 1 * * NumberAbsolute<1>; * //=> 1 * * NumberAbsolute<NegativeInfinity> * //=> PositiveInfinity * ``` */ export type NumberAbsolute<N extends number> = `${N}` extends `-${infer StringPositiveN}` ? StringToNumber<StringPositiveN> : N; export type Subtract<A extends number, B extends number> = number extends A | B ? number : [ IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>, IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity> ] extends infer R extends [boolean, boolean, boolean, boolean] ? Or<And<IsEqual<R[0], true>, IsEqual<R[2], false>>, And<IsEqual<R[3], true>, IsEqual<R[1], false>>> extends true ? PositiveInfinity : Or<And<IsEqual<R[1], true>, IsEqual<R[3], false>>, And<IsEqual<R[2], true>, IsEqual<R[0], false>>> extends true ? NegativeInfinity : true extends R[number] ? number : [IsNegative<A>, IsNegative<B>] extends infer R ? [false, false] extends R ? BuildTuple<A> extends infer R ? R extends [...BuildTuple<B>, ...infer R] ? R["length"] : number : never : LessThan<A, B> extends true ? number : [false, true] extends R ? Sum<A, NumberAbsolute<B>> : Subtract<NumberAbsolute<B>, NumberAbsolute<A>> : never : never; export type Sum<A extends number, B extends number> = number extends A | B ? number : [ IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>, IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity> ] extends infer R extends [boolean, boolean, boolean, boolean] ? Or<And<IsEqual<R[0], true>, IsEqual<R[3], false>>, And<IsEqual<R[2], true>, IsEqual<R[1], false>>> extends true ? PositiveInfinity : Or<And<IsEqual<R[1], true>, IsEqual<R[2], false>>, And<IsEqual<R[3], true>, IsEqual<R[0], false>>> extends true ? NegativeInfinity : true extends R[number] ? number : ([IsNegative<A>, IsNegative<B>] extends infer R ? [false, false] extends R ? [...BuildTuple<A>, ...BuildTuple<B>]["length"] : [true, true] extends R ? number : ArrayMax<[ NumberAbsolute<A>, NumberAbsolute<B> ]> extends infer Max_ ? ArrayMin<[ NumberAbsolute<A>, NumberAbsolute<B> ]> extends infer Min_ extends number ? Max_ extends A | B ? Subtract<Max_, Min_> : number : never : never : never) & number : never; export {};