Skip to content

Commit

Permalink
feat: IsStrictObject<T>
Browse files Browse the repository at this point in the history
  • Loading branch information
unional committed Sep 13, 2023
1 parent 0b4e9fc commit afac18a
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/lovely-horses-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"type-plus": minor
---

Add `IsStrictObject<T>` type.
9 changes: 1 addition & 8 deletions type-plus/ts/equal/equal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<A, B, Both, One, None> = And<
IsNever<A>,
Expand All @@ -14,14 +15,6 @@ type BothNever<A, B, Both, One, None> = And<

type BothAny<A, B, Both, One, None> = And<IsAny<A>, IsAny<B>, Both, Or<IsAny<A>, IsAny<B>, One, None>>

type IdentityEqual<A, B, Then, Else> = (<_>() => _ extends (A & _) | _ ? 1 : 2) extends <_>() => _ extends
| (B & _)
| _
? 1
: 2
? Then
: Else

/**
* Checks `A` and `B` are equal.
*
Expand Down
9 changes: 9 additions & 0 deletions type-plus/ts/equal/identity_equal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

/**
* This is a common equal check.
* It is good for some basic cases, but not for all.
*/
export type IdentityEqual<A, B, Then, Else> =
(<_>() => _ extends (A & _) | _ ? 1 : 2) extends (<_>() => _ extends | (B & _) | _ ? 1 : 2)
? Then
: Else
2 changes: 2 additions & 0 deletions type-plus/ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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'

2 changes: 1 addition & 1 deletion type-plus/ts/mix_types/box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down
21 changes: 21 additions & 0 deletions type-plus/ts/object/is_strict_object.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { it } from 'node:test'
import { testType, type IsStrictObject } from '../index.js'

it('returns false for special types', () => {
testType.equal<IsStrictObject<any>, false>(true)
testType.equal<IsStrictObject<unknown>, false>(true)
testType.equal<IsStrictObject<never>, false>(true)
testType.equal<IsStrictObject<void>, false>(true)
})

it('returns false for object literal', () => {
testType.equal<IsStrictObject<{ a: number }>, false>(true)
})

it('returns false for empty object literal', () => {
testType.equal<IsStrictObject<{}>, false>(true)
})

it('returns true for object', () => {
testType.equal<IsStrictObject<object>, true>(true)
})
14 changes: 14 additions & 0 deletions type-plus/ts/object/is_strict_object.ts
Original file line number Diff line number Diff line change
@@ -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<T, Then = true, Else = false> = IsObject<
T,
IdentityEqual<T, {}, Else, IsNever<keyof T, Then, Else>>,
Else
>

0 comments on commit afac18a

Please sign in to comment.