Skip to content

Commit

Permalink
update bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
Logicer16 committed Apr 5, 2024
1 parent 2c5e1b7 commit 0a56d6c
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 50 deletions.
59 changes: 37 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ Contents:

- [Install](#install)
- [Exports](#exports)
- [Arithmetic](#arithmetic)
- [`IntRange`](#intrange)
- [`IsAny`](#isany)
- [`IsUnion`](#isunion)
- [`UnionMax`](#unionmax)
- [`UnionToIntersection`](#uniontointersection)
- [`IsUnion`](#isunion)
- [Arithmetic](#arithmetic)
- [Unsafe](#unsafe)
- [Limitations](#limitations)

Expand All @@ -27,6 +28,10 @@ npm install --save-dev typescript @logicer/util-types

## Exports

### Arithmetic

Re-exports the types from [`ts-arithmetic`](https://github.com/Logicer16/ts-arithmetic)

### `IntRange`

Generate a union of number literals within a certain range. Accepts a start to the range (inclusive) and an end to the range (exclusive). If start is greater than end, `number` will be returned.
Expand Down Expand Up @@ -54,11 +59,39 @@ type BiggestNumbers = IntRange<1, 5001>;
type OverNineThousand = IntRange<9001, 10000>;
```

### `IsAny`

Returns a true if a type is `any` and otherwise false.

```ts
import type {IsAny} from "@logicer/util-types";

// true
type IsAnyTrue = IsAny<any>;

// false
type IsAnyFalse = IsAny<object>;
```

### `IsUnion`

Returns a true if a type is a union and otherwise false.

```ts
import type {IsUnion} from "@logicer/util-types";

// true
type IsUnionTrue = IsUnion<1 | 2 | 3>;

// false
type IsUnionFalse = IsUnion<1>;
```

### `UnionMax`

Find the greatest number in a union of numeric type literals. Accepts a union of numeric type literal and lower bound to begin searching at (inclusive). If the lower bound is greater than the lowest value in the union, `number` will be returned.

The number of items to search is limited to 6328 due to other [typescript limitations](#limitations). If the largest value is not found before this limit is reached, `number` will be returned instead.
The number of items to search is limited to 8001 due to other [typescript limitations](#limitations). If the largest value is not found before this limit is reached, `number` will be returned instead.

```ts
import type {UnionMax} from "@logicer/util-types";
Expand Down Expand Up @@ -103,28 +136,10 @@ type Union = A | B | C;
type Intersection = UnionToIntersection<Union>;
```

### `IsUnion`

Returns a true if a type is a union and otherwise false.

```ts
import type {IsUnion} from "@logicer/util-types";

// true
type IsUnionTrue = IsUnion<1 | 2 | 3>;

// false
type IsUnionFalse = IsUnion<1>;
```

### Arithmetic

Re-exports the types from [`ts-arithmetic`](https://github.com/Logicer16/ts-arithmetic)

### Unsafe

> [!WARNING]
> Unsafe contains internal types used to produces the types exported by this package. Use at your own risk.
> Unsafe contains internal types used to produces the types exported by this package. These types are unsupported and may change at any time. USE AT YOUR OWN RISK
## Limitations

Expand Down
2 changes: 2 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ const utilTypesConfigs = [
files: ["tests/**/*"],
rules: {
"@typescript-eslint/consistent-type-definitions": "off",
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": "off"
}
}
Expand Down
11 changes: 9 additions & 2 deletions tests/IntRange.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
/**
* @file Testing the `IntRange` type.
*/
import type {IntRange} from "@logicer/util-types";
import type {IntRange} from "../types/IntRange.d.ts";
import type {IsAny} from "../types/any.d.ts";

// Bounds:

type MaxRange = IntRange<0, 7260>;
const valid: MaxRange[] = [0, 7259];
// @ts-expect-error TS2322 Is `number`
const oneOver: MaxRange = 7260;
type OneOverRange = IntRange<0, 7261>;
type OneOverNumber = number extends OneOverRange ? true : false;
const OneOverNumber: OneOverNumber = true;
type OneOverAny = IsAny<OneOverRange>;
// @ts-expect-error TS2322
const oneOverAny: MaxRange = 7260;
const OneOverAny: OneOverAny = true;

// Documentation Examples:

Expand Down
17 changes: 12 additions & 5 deletions tests/UnionMax.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
/**
* @file Testing the `UnionMax` type.
*/
import type {UnionMax} from "@logicer/util-types";
import type {IsAny} from "../types/any.js";
import type {UnionMax} from "../types/UnionMax.js";

// Bounds:

type MaxRangedResult = UnionMax<6327 | 6328>;
const valid: MaxRangedResult = 6328;
// @ts-expect-error TS2322
const oneOverAny: MaxRangedResult = 10;
type MaxRangedResult = UnionMax<8001 | 8002>;
const valid: MaxRangedResult = 8002;
// @ts-expect-error TS2322 Is `number`
const altConstituent: MaxRangedResult = 8001;
type OneOver = UnionMax<8002 | 8003>;
type OneOverNumber = number extends OneOver ? true : false;
const oneOverNumber: OneOverNumber = true;
type OneOverAny = IsAny<OneOver>;
// @ts-expect-error TS2322
const oneOverAny: OneOverAny = true;

// Documentation Examples:

Expand Down
23 changes: 23 additions & 0 deletions tests/any.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @file Testing types related to the use of `any`.
*/
import type {IsAny} from "../types/any.js";

interface InterfaceWithContents {
// type-coverage:ignore-next-line
one: any;
}

interface EmptyInterface {}

const any: IsAny<any> = true;
const unknown: IsAny<unknown> = false;
const primitive: IsAny<number> = false;
const interfaceWithContents: IsAny<InterfaceWithContents> = false;
const emptyInterface: IsAny<EmptyInterface> = false;
const objectA: IsAny<object> = false;
/* eslint-disable @typescript-eslint/ban-types */
// type-coverage:ignore-next-line
const objectB: IsAny<Object> = false;
/* eslint-enable @typescript-eslint/ban-types */
const literal: IsAny<1> = false;
4 changes: 3 additions & 1 deletion tests/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/**
* @file Testing the interactions of between types in the package.
*/
import type {IntRange, UnionMax} from "@logicer/util-types";

import type {IntRange} from "../types/IntRange.js";
import type {UnionMax} from "../types/UnionMax.js";

// Documentation Examples:

Expand Down
2 changes: 1 addition & 1 deletion tests/unionsAndIntersections.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @file Testing types related to the use of unions and intersections.
*/
import {UnionToIntersection} from "../types/unionsAndIntersections.js";
import type {UnionToIntersection} from "../types/unionsAndIntersections.js";

type A = {one: 1};
type B = {two: 2};
Expand Down
17 changes: 8 additions & 9 deletions types/IntRange.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,29 @@ export namespace Unsafe {
>;

/**
* Iteratively use a type to enumerate over a given range, producing union whose constituents are the numeric literals of the numbers within that range.
* Recursively use a type to enumerate over a given range, producing union whose constituents are the numeric literals of the numbers within that range.
* @param End The value at which the range terminates (exclusive).
* @param Start The value at which the range begins (inclusive).
* @param Fallback The type to return when the depth is exhausted.
* @param DepthRemaining The remaining recursion depth available for types.
* @param Accumulator The array to add values to.
* @param ExpectedLength The computed length the accumulator is expected to be once the entire range has been enumerated.
* @param NewStart The computed start value of subsequent iterations.
* @param NewStart The computed start value of subsequent recursions.
* @returns {number} The modified `Accumulator`.
*/
export type BigEnumerate<
export type RecursivelyEnumerate<
End extends number,
Start extends number = 0,
Fallback = number,
// This is due to typescript limitations (cumulative type instantiation).
DepthRemaining extends number = 120,
DepthRemaining extends number = 1000,
Accumulator extends number[] = [],
ExpectedLength extends number = Subtract<End, Start>,
NewStart extends number = Add<Start, DepthRemaining>
> = ExpectedLength extends Accumulator["length"]
? Accumulator[number]
: DepthRemaining extends 0
? Fallback
: BigEnumerate<
: RecursivelyEnumerate<
End,
NewStart,
Fallback,
Expand Down Expand Up @@ -80,6 +79,6 @@ export namespace Unsafe {
*/
export type IntRange<
Start extends number,
End extends number,
Fallback = number
> = Unsafe.BigEnumerate<End, Start, Fallback>;
End extends number
// Limited depth due to typescript limitations (cumulative type instantiation).
> = Unsafe.RecursivelyEnumerate<End, Start, number, 120>;
20 changes: 10 additions & 10 deletions types/UnionMax.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,20 @@ export namespace Unsafe {
: {done: true; value: Value};

/**
* Iteratively use a type to iteratively remove constituent numeric literals from a union until a single value remains.
* Recursively use a type to iteratively remove constituent numeric literals from a union until a single value remains.
* @param Value The input union to process.
* @param Index The current start value to remove from the union.
* @param Fallback The type to return when the depth is exhausted.
* @param DepthRemaining The remaining recursion depth available for types.
* @param NewIndex The computed index of the subsequence iterations.
* @param Result The computed result of this iteration's consumption.
* @param NewIndex The computed index of the subsequence recursions.
* @param Result The computed result of this recursion's consumption.
* @returns {number | Fallback} The constituent of the input union with the greatest value. If the depth is exhausted, `Fallback` is returned instead. If the operation was unsuccessful, number is returned instead.
*/
export type BigUnionMaxConsume<
export type UnionMaxRecursivelyConsume<
Value extends number,
Index extends number = 0,
Fallback = number,
// This is due to typescript limitations (cumulative type instantiation).
DepthRemaining extends number = 112,
DepthRemaining extends number = 1000,
NewIndex extends number = Add<Index, DepthRemaining>,
Result extends {done: boolean; value: number} = UnionMaxConsume<
Value,
Expand All @@ -65,24 +64,25 @@ export namespace Unsafe {
? Result["value"]
: DepthRemaining extends 0
? Fallback
: BigUnionMaxConsume<
: UnionMaxRecursivelyConsume<
Result["value"],
NewIndex,
Fallback,
Subtract<DepthRemaining, 1>
>;
}

// Max value is the (DepthRemaining - 1)th triangle number.
// Max value is the ((DepthRemaining + 1)th triangle number) + 1.
/**
* Find the greatest number in a union.
*
* The maximum search range is 6328 due to other [typescript limitations](https://github.com/Logicer16/util-types?tab=readme-ov-file#limitations). If the range exceeds this limit, `number` will be returned instead.
* The maximum search range is 8001 due to other [typescript limitations](https://github.com/Logicer16/util-types?tab=readme-ov-file#limitations). If the range exceeds this limit, `number` will be returned instead.
* @param In A union of numeric literals to search.
* @param Start Searches from `Start` (inclusive) incrementally until the greatest value is reached. If this.
* @returns {number} A numeric literal representing the greatest value in a union. If the parameters are outside the capabilities of the type, `number` will be returned instead.
*/
export type UnionMax<
In extends number,
Start extends number = 0
> = Unsafe.BigUnionMaxConsume<In, Start>;
// Limited depth due to typescript limitations (cumulative type instantiation).
> = Unsafe.UnionMaxRecursivelyConsume<In, Start, number, 126>;
11 changes: 11 additions & 0 deletions types/any.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @file Types related to the use of `any`.
*/

/**
* Check if a type is `any`.
* @param Type The type to check.
* @returns {boolean} True if a type is `any` and otherwise false.
* @see https://stackoverflow.com/a/55541672
*/
export type IsAny<Type> = 0 extends Type & 1 ? true : false;
1 change: 1 addition & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export namespace Unsafe {
export type {Unsafe as Arithmetic} from "@logicer/ts-arithmetic";
}

export * from "./any.d.ts";
export * from "./UnionMax.d.ts";
export * from "./IntRange.d.ts";
export * from "./unionsAndIntersections.d.ts";
Expand Down

0 comments on commit 0a56d6c

Please sign in to comment.