From afac18a02688042389787fe9e68109e0bf77f3d8 Mon Sep 17 00:00:00 2001 From: unional Date: Tue, 12 Sep 2023 21:49:12 -0700 Subject: [PATCH] feat: IsStrictObject --- .changeset/lovely-horses-press.md | 5 +++++ type-plus/ts/equal/equal.ts | 9 +-------- type-plus/ts/equal/identity_equal.ts | 9 +++++++++ type-plus/ts/index.ts | 2 ++ type-plus/ts/mix_types/box.ts | 2 +- type-plus/ts/object/is_strict_object.spec.ts | 21 ++++++++++++++++++++ type-plus/ts/object/is_strict_object.ts | 14 +++++++++++++ 7 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 .changeset/lovely-horses-press.md create mode 100644 type-plus/ts/equal/identity_equal.ts create mode 100644 type-plus/ts/object/is_strict_object.spec.ts create mode 100644 type-plus/ts/object/is_strict_object.ts diff --git a/.changeset/lovely-horses-press.md b/.changeset/lovely-horses-press.md new file mode 100644 index 0000000000..1a96695765 --- /dev/null +++ b/.changeset/lovely-horses-press.md @@ -0,0 +1,5 @@ +--- +"type-plus": minor +--- + +Add `IsStrictObject` type. diff --git a/type-plus/ts/equal/equal.ts b/type-plus/ts/equal/equal.ts index cbbda22845..ea2f320d1f 100644 --- a/type-plus/ts/equal/equal.ts +++ b/type-plus/ts/equal/equal.ts @@ -4,6 +4,7 @@ import type { IsObject } from '../object/object_type.js' import type { Properties } from '../object/properties.js' import type { And, Or } from '../predicates/logical.js' import type { IsSymbol } from '../symbol/symbol_type.js' +import type { IdentityEqual } from './identity_equal.js' type BothNever = And< IsNever, @@ -14,14 +15,6 @@ type BothNever = And< type BothAny = And, IsAny, Both, Or, IsAny, One, None>> -type IdentityEqual = (<_>() => _ extends (A & _) | _ ? 1 : 2) extends <_>() => _ extends - | (B & _) - | _ - ? 1 - : 2 - ? Then - : Else - /** * Checks `A` and `B` are equal. * diff --git a/type-plus/ts/equal/identity_equal.ts b/type-plus/ts/equal/identity_equal.ts new file mode 100644 index 0000000000..f031a5be31 --- /dev/null +++ b/type-plus/ts/equal/identity_equal.ts @@ -0,0 +1,9 @@ + +/** + * This is a common equal check. + * It is good for some basic cases, but not for all. + */ +export type IdentityEqual = + (<_>() => _ extends (A & _) | _ ? 1 : 2) extends (<_>() => _ extends | (B & _) | _ ? 1 : 2) + ? Then + : Else diff --git a/type-plus/ts/index.ts b/type-plus/ts/index.ts index 692b269772..170ba8bb26 100644 --- a/type-plus/ts/index.ts +++ b/type-plus/ts/index.ts @@ -83,6 +83,7 @@ export type { export type { IsNotPositive, IsPositive, NonPositive, Positive } from './numeric/positive.js' export type { Required, RequiredExcept, RequiredPick } from './object/Required.js' export * from './object/index.js' +export type * from './object/is_strict_object.js' export * as ObjectPlus from './object/object_plus.js' export type { IsNotObject, IsObject, NotObjectType, ObjectType } from './object/object_type.js' export * from './predicates/index.js' @@ -123,3 +124,4 @@ export * from './unpartial.js' export * from './utils/index.js' export type { TypePlusOptions } from './utils/options.js' export type { IsNotVoid, IsVoid, NotVoidType, VoidType } from './void/void_type.js' + diff --git a/type-plus/ts/mix_types/box.ts b/type-plus/ts/mix_types/box.ts index 496054148d..05b7223755 100644 --- a/type-plus/ts/mix_types/box.ts +++ b/type-plus/ts/mix_types/box.ts @@ -2,7 +2,7 @@ import type { IsBigint } from '../bigint/bigint_type.js' import type { IsBoolean } from '../boolean/boolean_type.js' import type { IsFunction } from '../function/function_type.js' import type { IsNumber } from '../number/number_type.js' -import type { IsStrictObject } from '../object/object_type.js' +import type { IsStrictObject } from '../object/is_strict_object.js' import type { IsString } from '../string/string_type.js' import type { IsSymbol } from '../symbol/symbol_type.js' diff --git a/type-plus/ts/object/is_strict_object.spec.ts b/type-plus/ts/object/is_strict_object.spec.ts new file mode 100644 index 0000000000..b227f08f01 --- /dev/null +++ b/type-plus/ts/object/is_strict_object.spec.ts @@ -0,0 +1,21 @@ +import { it } from 'node:test' +import { testType, type IsStrictObject } from '../index.js' + +it('returns false for special types', () => { + testType.equal, false>(true) + testType.equal, false>(true) + testType.equal, false>(true) + testType.equal, false>(true) +}) + +it('returns false for object literal', () => { + testType.equal, false>(true) +}) + +it('returns false for empty object literal', () => { + testType.equal, false>(true) +}) + +it('returns true for object', () => { + testType.equal, true>(true) +}) diff --git a/type-plus/ts/object/is_strict_object.ts b/type-plus/ts/object/is_strict_object.ts new file mode 100644 index 0000000000..bb406a7dda --- /dev/null +++ b/type-plus/ts/object/is_strict_object.ts @@ -0,0 +1,14 @@ +import type { IdentityEqual } from '../equal/identity_equal.js' +import type { IsNever } from '../never/never_type.js' +import type { IsObject } from './object_type.js' + +/** + * 🎭 *validate* + * + * Validate that `T` is strictly the `object` type. + */ +export type IsStrictObject = IsObject< + T, + IdentityEqual>, + Else +>