Skip to content

Commit

Permalink
Implement KindGuard Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 committed Apr 25, 2024
1 parent 85891e3 commit a5a6737
Show file tree
Hide file tree
Showing 113 changed files with 3,348 additions and 206 deletions.
3 changes: 1 addition & 2 deletions example/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ const S = Date.now()
for (let i = 0; i < 1000; i++) {
Type.Composite([T, T, T])
}
console.dir(Type.Composite([T, T, T]), { depth: 100 })
console.log(Date.now() - S)

console.log(Date.now() - S)
1 change: 0 additions & 1 deletion src/type/composite/composite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ type TCompositeEvaluate<
> = R
// prettier-ignore
export type TComposite<T extends TSchema[]> = TCompositeEvaluate<T>

// prettier-ignore
export function Composite<T extends TSchema[]>(T: [...T], options: ObjectOptions = {}): TComposite<T> {
const K = CompositeKeys(T)
Expand Down
94 changes: 49 additions & 45 deletions src/type/guard/kind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

import * as ValueGuard from './value'
import { Kind, TransformKind, ReadonlyKind, OptionalKind } from '../symbols/index'
import { Kind, Hint, TransformKind, ReadonlyKind, OptionalKind } from '../symbols/index'
import { TransformOptions } from '../transform/index'
import { TTemplateLiteral } from '../template-literal/index'
import { TArray } from '../array/index'
Expand Down Expand Up @@ -66,179 +66,183 @@ import type { TVoid } from '../void/index'
import type { TDate } from '../date/index'
import type { TThis } from '../recursive/index'

/** `[Unsafe]` Returns true if this value has a Readonly symbol */
/** `[Kind-Only]` Returns true if this value has a Readonly symbol */
export function IsReadonly<T extends TSchema>(value: T): value is TReadonly<T> {
return ValueGuard.IsObject(value) && value[ReadonlyKind] === 'Readonly'
}
/** `[Unsafe]` Returns true if this value has a Optional symbol */
/** `[Kind-Only]` Returns true if this value has a Optional symbol */
export function IsOptional<T extends TSchema>(value: T): value is TOptional<T> {
return ValueGuard.IsObject(value) && value[OptionalKind] === 'Optional'
}
/** `[Unsafe]` Returns true if the given value is TAny */
/** `[Kind-Only]` Returns true if the given value is TAny */
export function IsAny(value: unknown): value is TAny {
return IsKindOf(value, 'Any')
}
/** `[Unsafe]` Returns true if the given value is TArray */
/** `[Kind-Only]` Returns true if the given value is TArray */
export function IsArray(value: unknown): value is TArray {
return IsKindOf(value, 'Array')
}
/** `[Unsafe]` Returns true if the given value is TAsyncIterator */
/** `[Kind-Only]` Returns true if the given value is TAsyncIterator */
export function IsAsyncIterator(value: unknown): value is TAsyncIterator {
return IsKindOf(value, 'AsyncIterator')
}
/** `[Unsafe]` Returns true if the given value is TBigInt */
/** `[Kind-Only]` Returns true if the given value is TBigInt */
export function IsBigInt(value: unknown): value is TBigInt {
return IsKindOf(value, 'BigInt')
}
/** `[Unsafe]` Returns true if the given value is TBoolean */
/** `[Kind-Only]` Returns true if the given value is TBoolean */
export function IsBoolean(value: unknown): value is TBoolean {
return IsKindOf(value, 'Boolean')
}
/** `[Unsafe]` Returns true if the given value is TConstructor */
/** `[Kind-Only]` Returns true if the given value is TConstructor */
export function IsConstructor(value: unknown): value is TConstructor {
return IsKindOf(value, 'Constructor')
}
/** `[Unsafe]` Returns true if the given value is TDate */
/** `[Kind-Only]` Returns true if the given value is TDate */
export function IsDate(value: unknown): value is TDate {
return IsKindOf(value, 'Date')
}
/** `[Unsafe]` Returns true if the given value is TFunction */
/** `[Kind-Only]` Returns true if the given value is TFunction */
export function IsFunction(value: unknown): value is TFunction {
return IsKindOf(value, 'Function')
}
/** `[Unsafe]` Returns true if the given value is TInteger */
/** `[Kind-Only]` Returns true if the given value is TInteger */
export function IsInteger(value: unknown): value is TInteger {
return IsKindOf(value, 'Integer')
}
/** `[Unsafe]` Returns true if the given schema is TProperties */
/** `[Kind-Only]` Returns true if the given schema is TProperties */
export function IsProperties(value: unknown): value is TProperties {
return ValueGuard.IsObject(value)
}
/** `[Unsafe]` Returns true if the given value is TIntersect */
/** `[Kind-Only]` Returns true if the given value is TIntersect */
export function IsIntersect(value: unknown): value is TIntersect {
return IsKindOf(value, 'Intersect')
}
/** `[Unsafe]` Returns true if the given value is TIterator */
/** `[Kind-Only]` Returns true if the given value is TIterator */
export function IsIterator(value: unknown): value is TIterator {
return IsKindOf(value, 'Iterator')
}
/** `[Unsafe]` Returns true if the given value is a TKind with the given name. */
/** `[Kind-Only]` Returns true if the given value is a TKind with the given name. */
export function IsKindOf<T extends string>(value: unknown, kind: T): value is Record<PropertyKey, unknown> & { [Kind]: T } {
return ValueGuard.IsObject(value) && Kind in value && value[Kind] === kind
}
/** `[Unsafe]` Returns true if the given value is TLiteral<string> */
/** `[Kind-Only]` Returns true if the given value is TLiteral<string> */
export function IsLiteralString(value: unknown): value is TLiteral<string> {
return IsLiteral(value) && ValueGuard.IsString(value.const)
}
/** `[Unsafe]` Returns true if the given value is TLiteral<number> */
/** `[Kind-Only]` Returns true if the given value is TLiteral<number> */
export function IsLiteralNumber(value: unknown): value is TLiteral<number> {
return IsLiteral(value) && ValueGuard.IsNumber(value.const)
}
/** `[Unsafe]` Returns true if the given value is TLiteral<boolean> */
/** `[Kind-Only]` Returns true if the given value is TLiteral<boolean> */
export function IsLiteralBoolean(value: unknown): value is TLiteral<boolean> {
return IsLiteral(value) && ValueGuard.IsBoolean(value.const)
}
/** `[Unsafe]` Returns true if the given value is TLiteral */
/** `[Kind-Only]` Returns true if the given value is TLiteral */
export function IsLiteral(value: unknown): value is TLiteral {
return IsKindOf(value, 'Literal')
}
/** `[Unsafe]` Returns true if the given value is a TMappedKey */
/** `[Kind-Only]` Returns true if the given value is a TMappedKey */
export function IsMappedKey(value: unknown): value is TMappedKey {
return IsKindOf(value, 'MappedKey')
}
/** `[Unsafe]` Returns true if the given value is TMappedResult */
/** `[Kind-Only]` Returns true if the given value is TMappedResult */
export function IsMappedResult(value: unknown): value is TMappedResult {
return IsKindOf(value, 'MappedResult')
}
/** `[Unsafe]` Returns true if the given value is TNever */
/** `[Kind-Only]` Returns true if the given value is TNever */
export function IsNever(value: unknown): value is TNever {
return IsKindOf(value, 'Never')
}
/** `[Unsafe]` Returns true if the given value is TNot */
/** `[Kind-Only]` Returns true if the given value is TNot */
export function IsNot(value: unknown): value is TNot {
return IsKindOf(value, 'Not')
}
/** `[Unsafe]` Returns true if the given value is TNull */
/** `[Kind-Only]` Returns true if the given value is TNull */
export function IsNull(value: unknown): value is TNull {
return IsKindOf(value, 'Null')
}
/** `[Unsafe]` Returns true if the given value is TNumber */
/** `[Kind-Only]` Returns true if the given value is TNumber */
export function IsNumber(value: unknown): value is TNumber {
return IsKindOf(value, 'Number')
}
/** `[Unsafe]` Returns true if the given value is TObject */
/** `[Kind-Only]` Returns true if the given value is TObject */
export function IsObject(value: unknown): value is TObject {
return IsKindOf(value, 'Object')
}
/** `[Unsafe]` Returns true if the given value is TPromise */
/** `[Kind-Only]` Returns true if the given value is TPromise */
export function IsPromise(value: unknown): value is TPromise {
return IsKindOf(value, 'Promise')
}
/** `[Unsafe]` Returns true if the given value is TRecord */
/** `[Kind-Only]` Returns true if the given value is TRecord */
export function IsRecord(value: unknown): value is TRecord {
return IsKindOf(value, 'Record')
}
/** `[Unsafe]` Returns true if the given value is TRef */
/** `[Kind-Only]` Returns true if this value is TRecursive */
export function IsRecursive(value: unknown): value is { [Hint]: 'Recursive' } {
return ValueGuard.IsObject(value) && Hint in value && value[Hint] === 'Recursive'
}
/** `[Kind-Only]` Returns true if the given value is TRef */
export function IsRef(value: unknown): value is TRef {
return IsKindOf(value, 'Ref')
}
/** `[Unsafe]` Returns true if the given value is TRegExp */
/** `[Kind-Only]` Returns true if the given value is TRegExp */
export function IsRegExp(value: unknown): value is TRegExp {
return IsKindOf(value, 'RegExp')
}
/** `[Unsafe]` Returns true if the given value is TString */
/** `[Kind-Only]` Returns true if the given value is TString */
export function IsString(value: unknown): value is TString {
return IsKindOf(value, 'String')
}
/** `[Unsafe]` Returns true if the given value is TSymbol */
/** `[Kind-Only]` Returns true if the given value is TSymbol */
export function IsSymbol(value: unknown): value is TSymbol {
return IsKindOf(value, 'Symbol')
}
/** `[Unsafe]` Returns true if the given value is TTemplateLiteral */
/** `[Kind-Only]` Returns true if the given value is TTemplateLiteral */
export function IsTemplateLiteral(value: unknown): value is TTemplateLiteral {
return IsKindOf(value, 'TemplateLiteral')
}
/** `[Unsafe]` Returns true if the given value is TThis */
/** `[Kind-Only]` Returns true if the given value is TThis */
export function IsThis(value: unknown): value is TThis {
return IsKindOf(value, 'This')
}
/** `[Unsafe]` Returns true of this value is TTransform */
/** `[Kind-Only]` Returns true of this value is TTransform */
export function IsTransform(value: unknown): value is { [TransformKind]: TransformOptions } {
return ValueGuard.IsObject(value) && TransformKind in value
}
/** `[Unsafe]` Returns true if the given value is TTuple */
/** `[Kind-Only]` Returns true if the given value is TTuple */
export function IsTuple(value: unknown): value is TTuple {
return IsKindOf(value, 'Tuple')
}
/** `[Unsafe]` Returns true if the given value is TUndefined */
/** `[Kind-Only]` Returns true if the given value is TUndefined */
export function IsUndefined(value: unknown): value is TUndefined {
return IsKindOf(value, 'Undefined')
}
/** `[Unsafe]` Returns true if the given value is TUnion */
/** `[Kind-Only]` Returns true if the given value is TUnion */
export function IsUnion(value: unknown): value is TUnion {
return IsKindOf(value, 'Union')
}
/** `[Unsafe]` Returns true if the given value is TUint8Array */
/** `[Kind-Only]` Returns true if the given value is TUint8Array */
export function IsUint8Array(value: unknown): value is TUint8Array {
return IsKindOf(value, 'Uint8Array')
}
/** `[Unsafe]` Returns true if the given value is TUnknown */
/** `[Kind-Only]` Returns true if the given value is TUnknown */
export function IsUnknown(value: unknown): value is TUnknown {
return IsKindOf(value, 'Unknown')
}
/** `[Unsafe]` Returns true if the given value is a raw TUnsafe */
/** `[Kind-Only]` Returns true if the given value is a raw TUnsafe */
export function IsUnsafe(value: unknown): value is TUnsafe<unknown> {
return IsKindOf(value, 'Unsafe')
}
/** `[Unsafe]` Returns true if the given value is TVoid */
/** `[Kind-Only]` Returns true if the given value is TVoid */
export function IsVoid(value: unknown): value is TVoid {
return IsKindOf(value, 'Void')
}
/** `[Unsafe]` Returns true if the given value is TKind */
/** `[Kind-Only]` Returns true if the given value is TKind */
export function IsKind(value: unknown): value is Record<PropertyKey, unknown> & { [Kind]: string } {
return ValueGuard.IsObject(value) && Kind in value && ValueGuard.IsString(value[Kind])
}
/** `[Unsafe]` Returns true if the given value is TSchema */
/** `[Kind-Only]` Returns true if the given value is TSchema */
export function IsSchema(value: unknown): value is TSchema {
// prettier-ignore
return (
Expand Down
55 changes: 3 additions & 52 deletions test/runtime/type/guard/index.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,3 @@
import './any'
import './array'
import './async-iterator'
import './awaited'
import './bigint'
import './boolean'
import './capitalize'
import './composite'
import './const'
import './constructor'
import './date'
import './deref'
import './enum'
import './exclude'
import './extract'
import './function'
import './indexed'
import './integer'
import './intersect'
import './iterator'
import './keyof'
import './kind'
import './literal'
import './lowercase'
import './mapped'
import './not'
import './null'
import './number'
import './object'
import './omit'
import './partial'
import './pick'
import './promise'
import './record'
import './recursive'
import './ref'
import './regexp'
import './required'
import './rest'
import './string'
import './symbol'
import './template-literal'
import './this'
import './tuple'
import './uint8array'
import './uncapitalize'
import './undefined'
import './union'
import './unknown'
import './unsafe'
import './uppercase'
import './void'
import './type/index'
import './kind/index'
import './value/index'
14 changes: 14 additions & 0 deletions test/runtime/type/guard/kind/any.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'

describe('guard/kind/TAny', () => {
it('Should guard for TAny', () => {
const R = KindGuard.IsAny(Type.Any())
Assert.IsTrue(R)
})
it('Should not guard for TAny', () => {
const R = KindGuard.IsAny(null)
Assert.IsFalse(R)
})
})
14 changes: 14 additions & 0 deletions test/runtime/type/guard/kind/array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'

describe('guard/kind/TArray', () => {
it('Should guard for TArray', () => {
const R = KindGuard.IsArray(Type.Array(Type.Number()))
Assert.IsTrue(R)
})
it('Should not guard for TArray', () => {
const R = KindGuard.IsArray(null)
Assert.IsFalse(R)
})
})
16 changes: 16 additions & 0 deletions test/runtime/type/guard/kind/async-iterator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'

describe('guard/kind/TAsyncIterator', () => {
it('Should guard for TAsyncIterator', () => {
const T = Type.AsyncIterator(Type.Any())
const R = KindGuard.IsAsyncIterator(T)
Assert.IsTrue(R)
})
it('Should not guard for TAsyncIterator', () => {
const T = null
const R = KindGuard.IsAsyncIterator(T)
Assert.IsFalse(R)
})
})
41 changes: 41 additions & 0 deletions test/runtime/type/guard/kind/awaited.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'

describe('guard/kind/Awaited', () => {
it('Should guard for Awaited 1', () => {
const T = Type.Awaited(Type.String())
const R = KindGuard.IsString(T)
Assert.IsTrue(R)
})
it('Should guard for Awaited 2', () => {
const T = Type.Awaited(Type.Promise(Type.String()))
const R = KindGuard.IsString(T)
Assert.IsTrue(R)
})
it('Should guard for Awaited 3', () => {
const T = Type.Awaited(Type.Awaited(Type.Promise(Type.String())))
const R = KindGuard.IsString(T)
Assert.IsTrue(R)
})
it('Should guard for Awaited 4', () => {
const T = Type.Awaited(Type.Union([Type.Promise(Type.Promise(Type.String()))]))
Assert.IsTrue(KindGuard.IsString(T))
})
it('Should guard for Awaited 5', () => {
const T = Type.Awaited(Type.Union([Type.Promise(Type.Promise(Type.String())), Type.Number()]))
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsTrue(KindGuard.IsString(T.anyOf[0]))
Assert.IsTrue(KindGuard.IsNumber(T.anyOf[1]))
})
it('Should guard for Awaited 6', () => {
const T = Type.Awaited(Type.Intersect([Type.Promise(Type.Promise(Type.String()))]))
Assert.IsTrue(KindGuard.IsString(T))
})
it('Should guard for Awaited 7', () => {
const T = Type.Awaited(Type.Intersect([Type.Promise(Type.Promise(Type.String())), Type.Number()]))
Assert.IsTrue(KindGuard.IsIntersect(T))
Assert.IsTrue(KindGuard.IsString(T.allOf[0]))
Assert.IsTrue(KindGuard.IsNumber(T.allOf[1]))
})
})

0 comments on commit a5a6737

Please sign in to comment.