From de546a296f4d8ccee6a6f86a8a1f99e9d0c8a625 Mon Sep 17 00:00:00 2001 From: unional Date: Sun, 24 Sep 2023 21:24:21 -0700 Subject: [PATCH] feat: udpate IsBigint IsNotBigint --- type-plus/ts/bigint/bigint_type.spec.ts | 57 --------- type-plus/ts/bigint/bigint_type.ts | 21 ---- type-plus/ts/bigint/is_bigint.spec.ts | 42 +++++-- type-plus/ts/bigint/is_bigint.ts | 72 +++++++++-- type-plus/ts/bigint/is_not_bigint.spec.ts | 40 +++++-- type-plus/ts/bigint/is_not_bigint.ts | 68 ++++++++++- type-plus/ts/bigint/not_bigint_type.spec.ts | 55 --------- type-plus/ts/bigint/not_bigint_type.ts | 15 --- type-plus/ts/bigint/readme.md | 126 ++++++++++++++++++-- type-plus/ts/index.ts | 2 - type-plus/ts/math/abs.ts | 5 +- type-plus/ts/mix_types/box.ts | 2 +- type-plus/ts/undefined/is_not_undefined.ts | 1 + 13 files changed, 308 insertions(+), 198 deletions(-) delete mode 100644 type-plus/ts/bigint/bigint_type.spec.ts delete mode 100644 type-plus/ts/bigint/bigint_type.ts delete mode 100644 type-plus/ts/bigint/not_bigint_type.spec.ts delete mode 100644 type-plus/ts/bigint/not_bigint_type.ts diff --git a/type-plus/ts/bigint/bigint_type.spec.ts b/type-plus/ts/bigint/bigint_type.spec.ts deleted file mode 100644 index 97fde0d5a0..0000000000 --- a/type-plus/ts/bigint/bigint_type.spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { it } from '@jest/globals' -import { testType, type BigintType } from '../index.js' - -it('returns T if T is bigint', () => { - testType.equal, bigint>(true) -}) - -it('returns T if T is bigint literals', () => { - testType.equal, 0n>(true) - testType.equal, 1n>(true) - testType.equal, -1n>(true) - testType.equal, 11111111111111111111111111111111n>(true) -}) - -it('returns never for special types', () => { - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) -}) - -it('returns never for other types', () => { - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never>(true) - testType.never void>>(true) -}) - -it('returns never for union type', () => { - testType.never>(true) - testType.never>(true) -}) - -it('returns T for intersection type', () => { - testType.equal, bigint & { a: 1 }>(true) -}) - -it('can override Then/Else', () => { - testType.equal, 1>(true) - testType.equal, 1>(true) - - testType.equal, 2>(true) - testType.equal, 2>(true) - testType.equal, 2>(true) - testType.equal, 2>(true) -}) diff --git a/type-plus/ts/bigint/bigint_type.ts b/type-plus/ts/bigint/bigint_type.ts deleted file mode 100644 index 6ac54de0ee..0000000000 --- a/type-plus/ts/bigint/bigint_type.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { IsAnyOrNever } from '../mix_types/is_any_or_never.js' -import type { $Else, $SelectionBranch, $Then } from '../type_plus/branch/selection.js' - -/** - * Check if the type `T` is exactly `bigint`. - * - * ```ts - * type R = BigintType // bigint - * - * type R = BigintType<1n> // never - * type R = BigintType // never - * type R = BigintType // never - * type R = BigintType // never - * ``` - */ -export type BigintType = IsAnyOrNever< -T, -$SelectionBranch> extends infer R -? R extends $Then ? Else -: R extends $Else ? [T] extends [bigint] ? Then : Else -: never : never diff --git a/type-plus/ts/bigint/is_bigint.spec.ts b/type-plus/ts/bigint/is_bigint.spec.ts index 1d8ed573ff..0496fab0ab 100644 --- a/type-plus/ts/bigint/is_bigint.spec.ts +++ b/type-plus/ts/bigint/is_bigint.spec.ts @@ -1,5 +1,5 @@ import { it } from '@jest/globals' -import { testType, type IsBigint } from '../index.js' +import { testType, type IsBigint, type $Then, type $Else } from '../index.js' it('returns true for bigint', () => { testType.true>(true) @@ -35,20 +35,42 @@ it('returns false for other types', () => { testType.false void>>(true) }) -it('returns false for union type', () => { - testType.false>(true) +it('distributes for union type', () => { + testType.equal, boolean>(true) + testType.equal, boolean>(true) }) it('returns true for interaction type', () => { testType.true>(true) + testType.true>(true) }) -it('can override Then/Else', () => { - testType.equal, 1>(true) - testType.equal, 1>(true) +it('works as filter', () => { + testType.equal, 1n>(true) - testType.equal, 2>(true) - testType.equal, 2>(true) - testType.equal, 2>(true) - testType.equal, 2>(true) + testType.equal, never>(true) + testType.equal, never>(true) + testType.equal, never>(true) + + testType.equal, 1n>(true) + + testType.equal, unknown>(true) + testType.equal, unknown>(true) +}) + +it('can disable union distribution', () => { + testType.equal, boolean>(true) + testType.equal, false>(true) +}) + +it('works with unique branches', () => { + testType.equal, $Then>(true) + testType.equal, $Then>(true) + + testType.equal, $Else>(true) + testType.equal, $Else>(true) + testType.equal, $Else>(true) + testType.equal, $Else>(true) + + testType.equal, $Then | $Else>(true) }) diff --git a/type-plus/ts/bigint/is_bigint.ts b/type-plus/ts/bigint/is_bigint.ts index 31477c5499..7a7fa2c6d3 100644 --- a/type-plus/ts/bigint/is_bigint.ts +++ b/type-plus/ts/bigint/is_bigint.ts @@ -1,15 +1,71 @@ -import type { BigintType } from './bigint_type.js' +import type { SelectWithDistribute } from '../type_plus/branch/select_with_distribute.js' /** - * Is the type `T` exactly `bigint`. + * 🎭 *predicate* * + * Validate if `T` is `bigint` or `bigint` literals. + * + * @example * ```ts - * type R = IsBigint // true + * type R = isBigint // true + * type R = isBigint<1n> // true + * + * type R = isBigint // false + * type R = isBigint // false + * type R = isBigint // false * - * type R = IsBigint<1n> // false - * type R = IsBigint // false - * type R = IsBigint // false - * type R = IsBigint // false + * type R = isBigint // boolean + * ``` + * + * 🔢 *customize* + * + * Filter to ensure `T` is `bigint` or `bigint` literals, otherwise returns `never`. + * + * @example + * ```ts + * type R = isBigint // bigint + * type R = isBigint<1n, { selection: 'filter' }> // bigint + * + * type R = isBigint // never + * type R = isBigint // never + * type R = isBigint // never + * + * type R = isBigint // bigint + * ``` + * + * 🔢 *customize* + * + * Filter to ensure `T` is `bigint` or `bigint` literals, otherwise returns `unknown`. + * + * @example + * ```ts + * type R = isBigint // unknown + * type R = isBigint // unknown + * ``` + * + * 🔢 *customize*: + * + * Disable distribution of union types. + * + * ```ts + * type R = isBigint // boolean + * type R = isBigint // false + * ``` + * + * 🔢 *customize* + * + * Use unique branch identifiers to allow precise processing of the result. + * + * @example + * ```ts + * type R = isBigint // $Then + * type R = isBigint // $Else * ``` */ -export type IsBigint = BigintType +export type IsBigint = SelectWithDistribute + +export namespace IsBigint { + export type $Options = SelectWithDistribute.$Options + export type $Default = SelectWithDistribute.$Default + export type $Branch = SelectWithDistribute.$Branch +} diff --git a/type-plus/ts/bigint/is_not_bigint.spec.ts b/type-plus/ts/bigint/is_not_bigint.spec.ts index 05bb631198..3daf87fa8e 100644 --- a/type-plus/ts/bigint/is_not_bigint.spec.ts +++ b/type-plus/ts/bigint/is_not_bigint.spec.ts @@ -1,5 +1,5 @@ import { it } from '@jest/globals' -import { testType, type IsNotBigint } from '../index.js' +import { testType, type $Else, type $Then, type IsNotBigint } from '../index.js' it('returns false for bigint', () => { testType.false>(true) @@ -35,20 +35,40 @@ it('returns true for other types', () => { testType.true void>>(true) }) -it('returns true for union type', () => { - testType.true>(true) +it('distributes over union type', () => { + testType.equal, boolean>(true) +}) + +it('can disable union distribution', () => { + testType.equal, boolean>(true) + testType.equal, true>(true) }) it('returns false for interaction type', () => { testType.false>(true) }) -it('can override Then/Else', () => { - testType.equal, 2>(true) - testType.equal, 2>(true) +it('works as filter', () => { + testType.equal, never>(true) + + testType.equal, never>(true) + testType.equal, unknown>(true) + testType.equal, string | boolean>(true) + + testType.equal, string>(true) + + testType.equal, string | boolean>(true) + testType.equal, unknown>(true) +}) + +it('works with unique branches', () => { + testType.equal, $Else>(true) + testType.equal, $Else>(true) + + testType.equal, $Then>(true) + testType.equal, $Then>(true) + testType.equal, $Then>(true) + testType.equal, $Then>(true) - testType.equal, 1>(true) - testType.equal, 1>(true) - testType.equal, 1>(true) - testType.equal, 1>(true) + testType.equal, $Then | $Else>(true) }) diff --git a/type-plus/ts/bigint/is_not_bigint.ts b/type-plus/ts/bigint/is_not_bigint.ts index d4bf803d84..900d3b73d5 100644 --- a/type-plus/ts/bigint/is_not_bigint.ts +++ b/type-plus/ts/bigint/is_not_bigint.ts @@ -1,15 +1,71 @@ -import type { BigintType } from './bigint_type.js' +import type { SelectInvertWithDistribute } from '../type_plus/branch/select_invert_with_distribute.js' /** - * Is the type `T` not exactly `null`. + * 🎭 *predicate* * + * Validate if `T` is not `bigint` nor `bigint` literals. + * + * @example * ```ts * type R = IsNotBigint // false + * type R = IsNotBigint<1n> // false * - * type R = IsNotBigint<1n> // true - * type R = IsNotBigint // true - * type R = IsNotBigint // true + * type R = IsNotBigint // true * type R = IsNotBigint // true + * type R = IsNotBigint // true + * ``` + * + * 🔢 *customize* + * + * Filter to ensure `T` is not `bigint` nor `bigint` literals, otherwise returns `never`. + * + * @example + * ```ts + * type R = IsNotBigint // never + * type R = IsNotBigint<1n, { selection: 'filter' }> // never + * + * type R = IsNotBigint // never + * type R = IsNotBigint // unknown + * type R = IsNotBigint // string | boolean + * ``` + * + * 🔢 *customize* + * + * Filter to ensure `T` is not `bigint` nor `bigint` literals, otherwise returns `unknown`. + * + * @example + * ```ts + * type R = IsNotBigint // unknown + * type R = IsNotBigint<1n, { selection: 'filter-unknown' }> // unknown + * + * type R = IsNotBigint // string | boolean + * type R = IsNotBigint // unknown + * ``` + * + * 🔢 *customize* + * + * Disable distribution of union types. + * + * @example + * ```ts + * type R = IsNotBigint // boolean + * type R = IsNotBigint // true + * ``` + * + * 🔢 *customize* + * + * Use unique branch identifiers to allow precise processing of the result. + * + * @example + * ```ts + * type R = IsNotBigint // $Then + * type R = IsNotBigint // $Else * ``` */ -export type IsNotBigint = BigintType +export type IsNotBigint = SelectInvertWithDistribute + +export namespace IsNotBigint { + export type $Options = SelectInvertWithDistribute.$Options + export type $Default = SelectInvertWithDistribute.$Default + export type $Branch = SelectInvertWithDistribute.$Branch +} diff --git a/type-plus/ts/bigint/not_bigint_type.spec.ts b/type-plus/ts/bigint/not_bigint_type.spec.ts deleted file mode 100644 index f3f0332b90..0000000000 --- a/type-plus/ts/bigint/not_bigint_type.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { it } from '@jest/globals' -import { testType, type NotBigintType } from '../index.js' - -it('returns never if T is bigint', () => { - testType.never>(true) -}) - -it('returns never if T is bigint literals', () => { - testType.equal, never>(true) - testType.equal, never>(true) -}) - -it('returns T for special types', () => { - testType.equal, any>(true) - testType.equal, unknown>(true) - testType.equal, void>(true) - testType.equal, never>(true) -}) - -it('returns T for other types', () => { - testType.equal, undefined>(true) - testType.equal, null>(true) - testType.equal, boolean>(true) - testType.equal, true>(true) - testType.equal, false>(true) - testType.equal, number>(true) - testType.equal, 1>(true) - testType.equal, string>(true) - testType.equal, ''>(true) - testType.equal, symbol>(true) - testType.equal, {}>(true) - testType.equal, string[]>(true) - testType.equal, []>(true) - testType.equal, Function>(true) - testType.equal void>, () => void>(true) -}) - -it('returns T for union type', () => { - testType.equal, bigint | 1>(true) - testType.equal, bigint | 'a'>(true) -}) - -it('returns never for intersection type', () => { - testType.equal, never>(true) -}) - -it('can override Then/Else', () => { - testType.equal, 2>(true) - testType.equal, 2>(true) - - testType.equal, 1>(true) - testType.equal, 1>(true) - testType.equal, 1>(true) - testType.equal, 1>(true) -}) diff --git a/type-plus/ts/bigint/not_bigint_type.ts b/type-plus/ts/bigint/not_bigint_type.ts deleted file mode 100644 index 04ee98c146..0000000000 --- a/type-plus/ts/bigint/not_bigint_type.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { BigintType } from './bigint_type.js' - -/** - * Check if the type `T` is not exactly `null`. - * - * ```ts - * type R = NotBigintType // never - * - * type R = NotBigintType<1n> // 1n - * type R = NotBigintType // number - * type R = NotBigintType // string | boolean - * type R = NotBigintType // unknown - * ``` - */ -export type NotBigintType = BigintType diff --git a/type-plus/ts/bigint/readme.md b/type-plus/ts/bigint/readme.md index cfa23ee44a..7e2abf9d90 100644 --- a/type-plus/ts/bigint/readme.md +++ b/type-plus/ts/bigint/readme.md @@ -2,26 +2,128 @@ `bigint` is a type to represent integers that are too large to be represented by a `number`. -## Type Checking +## [IsBigint](./is_bigint.ts) + +`IsBigint` + +🎭 *predicate* + +Validate if `T` is `bigint` or `bigint` literals. + +```ts +type R = isBigint // true +type R = isBigint<1n> // true + +type R = isBigint // false +type R = isBigint // false +type R = isBigint // false + +type R = isBigint // boolean +``` + +🔢 *customize* + +Filter to ensure `T` is `bigint` or `bigint` literals, otherwise returns `never`. + +```ts +type R = isBigint // bigint +type R = isBigint<1n, { selection: 'filter' }> // bigint + +type R = isBigint // never +type R = isBigint // never +type R = isBigint // never -The `BigintType` and friends are used to check if a type is `bigint` or not. +type R = isBigint // bigint +``` + +🔢 *customize* + +Filter to ensure `T` is `bigint` or `bigint` literals, otherwise returns `unknown`. + +```ts +type R = isBigint // unknown +type R = isBigint // unknown +``` + +🔢 *customize*: -They are loose type checks, meaning they match `bigint` and bigint literals, -as well as intersection types. +Disable distribution of union types. ```ts -import type { BigintType } from 'type-plus' +type R = isBigint // boolean +type R = isBigint // false +``` + +🔢 *customize* -type R = BigintType // bigint +Use unique branch identifiers to allow precise processing of the result. -type R = BigintType<1n> // bigint -type R = BigintType // bigint +```ts +type R = isBigint // $Then +type R = isBigint // $Else ``` -- [`BigintType`](bigint_type.ts#L15): check if `T` is `bigint` or bigint literal. -- [`IsBigint`](bigint_type.ts#L47): check if `T` is not `bigint`. -- [`IsNotBigInt`](bigint_type.ts#L61): is `T` not `bigint`. +## [IsNotBigint](./is_not_bigint.ts) + +`IsNotBigint` + +🎭 *predicate* + +Validate if `T` is not `bigint` nor `bigint` literals. + +```ts +type R = IsNotBigint // false +type R = IsNotBigint<1n> // false + +type R = IsNotBigint // true +type R = IsNotBigint // true +type R = IsNotBigint // true +``` + +🔢 *customize* + +Filter to ensure `T` is not `bigint` nor `bigint` literals, otherwise returns `never`. + +```ts +type R = IsNotBigint // never +type R = IsNotBigint<1n, { selection: 'filter' }> // never + +type R = IsNotBigint // never +type R = IsNotBigint // unknown +type R = IsNotBigint // string | boolean +``` + +🔢 *customize* + +Filter to ensure `T` is not `bigint` nor `bigint` literals, otherwise returns `unknown`. + +```ts +type R = IsNotBigint // unknown +type R = IsNotBigint<1n, { selection: 'filter-unknown' }> // unknown + +type R = IsNotBigint // string | boolean +type R = IsNotBigint // unknown +``` + +🔢 *customize* + +Disable distribution of union types. + +```ts +type R = IsNotBigint // boolean +type R = IsNotBigint // true +``` + +🔢 *customize* + +Use unique branch identifiers to allow precise processing of the result. + +```ts +type R = IsNotBigint // $Then +type R = IsNotBigint // $Else +``` + +## Type Checking --- diff --git a/type-plus/ts/index.ts b/type-plus/ts/index.ts index 84e98c4d6d..2e03361b58 100644 --- a/type-plus/ts/index.ts +++ b/type-plus/ts/index.ts @@ -21,11 +21,9 @@ export type { IsNotStrictArray, IsStrictArray, NotStrictArrayType, StrictArrayTy export type { PropUnion, UnionOfProps } from './array/union_of_props.js' export type { UnionOfValues } from './array/union_of_values.js' export { assertType } from './assertion/assert_type.js' -export type * from './bigint/bigint_type.js' export type { StringToBigint } from './bigint/cast.js' export type * from './bigint/is_bigint.js' export type * from './bigint/is_not_bigint.js' -export type * from './bigint/not_bigint_type.js' export type { IsNotStrictBigint, IsStrictBigint, diff --git a/type-plus/ts/math/abs.ts b/type-plus/ts/math/abs.ts index 6f059eedb3..9302da5905 100644 --- a/type-plus/ts/math/abs.ts +++ b/type-plus/ts/math/abs.ts @@ -14,5 +14,8 @@ import type { IsNumber } from '../number/number_type.js' export type Abs = IsNumber< N, [number] extends [N] ? Fail : `${N}` extends `-${infer P extends number}` ? P : N, - IsBigint + IsBigint extends infer R + ? R extends true ? [bigint] extends [N] ? Fail : `${N}` extends `-${infer P extends bigint}` ? P : N + : Fail + : never > diff --git a/type-plus/ts/mix_types/box.ts b/type-plus/ts/mix_types/box.ts index 1ac3e745aa..7d67b0d043 100644 --- a/type-plus/ts/mix_types/box.ts +++ b/type-plus/ts/mix_types/box.ts @@ -44,7 +44,7 @@ export type Box = IsSymbol< T, Symbol, - IsBigint + IsBigint > > > diff --git a/type-plus/ts/undefined/is_not_undefined.ts b/type-plus/ts/undefined/is_not_undefined.ts index a6452e5a5f..762005bb31 100644 --- a/type-plus/ts/undefined/is_not_undefined.ts +++ b/type-plus/ts/undefined/is_not_undefined.ts @@ -5,6 +5,7 @@ import type { SelectInvertWithDistribute } from '../type_plus/branch/select_inve * * Validate if `T` is not `undefined`. * + * @example * ```ts * type R = IsNotUndefined // false *