import { IndexOfHighestNumber, TupleOf } from './Array';
import { Not, Or } from './Boolean';
import { Includes, PadStart, StartsWith, Tail, ToString } from './String';
import { Equals } from './misc';
import { ListOf } from 'ts-toolbelt/out/Union/ListOf';
type _PrependNextNum> = A['length'] extends infer T ? [T, ...A] extends [...infer X] ? X : never : never;
type _Enumerate, N extends number> = number extends N ? number[] : N extends A['length'] ? A : _Enumerate<_PrependNextNum, N>;
/**
* creates a union type of numbers from 0 to generic `N`
* @example
* type Foo = Enumerate<3> //0|1|2
* @see https://stackoverflow.com/a/63918062
*/
export type Enumerate = _Enumerate<[], N>[never];
/**
* creates a range type of numbers from generics `FROM` (inclusive) to `TO` (inclusive)
* @example
* type Foo = RangeType<2, 5> //2|3|4|5
* @see https://stackoverflow.com/a/63918062
*/
export type RangeType = Exclude, Enumerate> | TO;
/**
* adds two `number` types together
* @example
* type Foo = Add<2, 3> //5
*/
export type Add = [
...TupleOf,
...TupleOf
]['length'] & number;
/**
* subtracts `N2` from `N1`
* @example
* type Foo = Subtract<5, 2> //3
*/
export type Subtract = TupleOf extends readonly [
...TupleOf,
...infer R
] ? R['length'] : never;
type _MultiAdd = IterationsLeft extends 0 ? Accumulator : _MultiAdd, Decrement>;
/**
* multiplies `N1` by `N2`
*
* **WARNING**: currently fails on big numbers
* @example
* type Foo = Multiply<2, 3> //6
* @see https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f
*/
export type Multiply = number extends N1 | N2 ? number : {
[K2 in N2]: {
[K1 in N1]: _MultiAdd;
}[N1];
}[N2];
type _AtTerminus = Dividee extends 0 ? true : Divider extends 0 ? true : false;
type _LessThanTerminus = _AtTerminus extends true ? Equals extends true ? false : Dividee extends 0 ? true : false : _LessThanTerminus, Decrement>;
type _MultiSub = _LessThanTerminus extends true ? QuotientAccumulator : _MultiSub, Divider, Increment>;
/**
* divides `N1` by `N2`
*
* **WARNING**: currently fails on big numbers
* @example
* type Foo = Divide<6, 3> //2
* @see https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f
*/
export type Divide = number extends N1 | N2 ? number : {
[K2 in N2]: {
[K1 in N1]: _MultiSub;
}[N1];
}[N2];
/**
* gets the remainder of `Divide`
* @example
* type Foo = Modulo<7, 4> //3
* @see https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f
*/
export type Modulo = _LessThanTerminus extends true ? N1 : Modulo, N2>;
type PowerTailRec = number extends PowerOf ? number : PowerOf extends 0 ? Result : PowerTailRec, Multiply>;
/**
* raises the value of `Num` to the power of the `PowerOf` parameter.
*/
export type Power = PowerTailRec;
/**
* raises the value of `Num` to the power of 2
*/
export type Square = Power;
type FactorialTailRec = T extends 1 ? Result : FactorialTailRec, Multiply>;
export type Factorial = number extends T ? number : FactorialTailRec;
/**
* checks whether a number is positive or negative
*/
export type IsPositive = `${T}` extends `-${number}` ? false : true;
/**
* adds 1 to `T`
*/
export type Increment = Add;
/** subtracts 1 from `T` */
export type Decrement = Subtract;
/**
* adds leading zeros to a number until it reaches a specified length
* @example
* type Foo = LeadingZeros<12, 5> //'00012'
* type Bar = LeadingZeros<-12, 5> //'-00012'
*/
export type LeadingZeros = number extends Num | Length ? ToString : IsPositive extends true ? PadStart, Length, '0'> : `-${PadStart>, Length, '0'>}`;
/**
* creates a stringified ordinal value for the given number
* @example
* type First = Ordinal<1> //1st
* type Third = Ordinal<3> //3rd
*/
export type Ordinal = number extends T ? `${number}${'st' | 'nd' | 'rd' | 'th'}` : {
[Num in T]: `${Num}${Modulo extends infer Mod ? Mod extends 1 ? 'st' : Mod extends 2 ? 'nd' : Mod extends 3 ? 'rd' : 'th' : never}`;
}[T];
/** `true` if `Num1` is greater than `Num2`, else `false` */
export type IsGreaterThan = {
[Num1 in Num1s]: {
[Num2 in Num2s]: TupleOf extends [never, ...TupleOf, ...never[]] ? true : false;
}[Num2s];
}[Num1s];
export type IsGreaterOrEqual = {
[Num1 in Num1s]: {
[Num2 in Num2s]: Or | Equals>;
}[Num2s];
}[Num1s];
export type IsLessThan = {
[Num1 in Num1s]: {
[Num2 in Num2s]: Not>;
}[Num2s];
}[Num1s];
export type IsLessOrEqual = Not>;
/** gets the highest number in a union of numbers */
export type HighestNumber = ListOf[IndexOfHighestNumber>];
/** shifts the bits of `Num` left by the given `Count` */
export type LeftShift = Multiply>;
/** shifts the bits of `Num` right by the given `Count` */
export type RightShift = Divide>;
/**
* a `number` that cannot have a decimal
* @example
* declare const foo = (num: Integer): void
* foo(1) //no error
* foo(1.2) //error
*/
export type Integer = number extends T ? never : Includes<`${T}`, '.'> extends true ? never : T;
/**
* a `number` that can only be positive
* @example
* declare const foo = (num: PositiveNumber): void
* foo(1) //no error
* foo(-1) //error
*/
export type PositiveNumber = number extends T ? never : StartsWith<`${T}`, '-'> extends true ? never : T;
/**
* a `number` that can only be negative
* @example
* declare const foo = (num: NegativeNumber): void
* foo(-1) //no error
* foo(1) //error
*/
export type NegativeNumber = number extends T ? never : PositiveNumber extends never ? T : never;
export type StringifiedNumber = `${number}` | `${'-' | '+' | ''}Infinity`;
export type ToNumber = T extends `${infer Result extends number}` ? Result : T extends StringifiedNumber ? number : undefined | (string extends T ? number : never);
export {};
//# sourceMappingURL=Number.d.ts.map