This commit is contained in:
sinclair
2025-12-24 15:44:34 +09:00
commit 13d553220c
1047 changed files with 80931 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
// --------------------------------------------------------------------
// $id deletion was omitted from 0.26.0 to reduce complexity overhead.
// --------------------------------------------------------------------
// import { Type } from '@sinclair/typebox'
// import { Assert } from '../../assert'
// describe('type/Clone', () => {
// it('Should retain source type $id for cloned objects', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Object({ x: S, y: S })
// Assert.equal(T.properties.x.$id, undefined)
// Assert.equal(T.properties.y.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should retain source type $id when composing objects with cloned arrays', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Function([S], S)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Array', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Array(S)
// Assert.equal(T.items.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Composite', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Composite([Type.Object({ a: S }), Type.Object({ b: S })])
// Assert.equal(T.properties.a.$id, undefined)
// Assert.equal(T.properties.b.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Constructor', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Constructor([S], S)
// Assert.equal(T.parameters[0].$id, undefined)
// Assert.equal(T.returns.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Function', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Function([S], S)
// Assert.equal(T.parameters[0].$id, undefined)
// Assert.equal(T.returns.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Intersect', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Intersect([S, S])
// Assert.equal(T.allOf[0].$id, undefined)
// Assert.equal(T.allOf[1].$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Intersect with unevaluatedProperties', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Intersect([S, S], { unevaluatedProperties: S })
// // @ts-ignore
// Assert.equal(T.unevaluatedProperties.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Not', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Not(S, S)
// Assert.equal(T.allOf[0].not.$id, undefined)
// Assert.equal(T.allOf[1].$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Object', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Object({ x: S, y: S })
// Assert.equal(T.properties.x.$id, undefined)
// Assert.equal(T.properties.y.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for nested Object', () => {
// const S = Type.String({ $id: 'S' })
// const N = Type.Object({ s: S }, { $id: 'N' })
// const T = Type.Object({ x: S, y: S, z: N })
// Assert.equal(T.properties.x.$id, undefined)
// Assert.equal(T.properties.y.$id, undefined)
// Assert.equal(T.properties.z.$id, undefined)
// Assert.equal(T.properties.z.properties.s.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Object additionalProperties', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Object({}, { additionalProperties: S })
// // @ts-ignore
// Assert.equal(T.additionalProperties!.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Promise', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Promise(S)
// Assert.equal(T.item.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Record', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Record(Type.String(), S)
// Assert.equal(T.patternProperties['^.*$'].$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Tuple', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Tuple([S, S])
// Assert.equal(T.items![0]!.$id, undefined)
// Assert.equal(T.items![1]!.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should remove cloned $id for Union', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Union([S, S])
// Assert.equal(T.anyOf[0]!.$id, undefined)
// Assert.equal(T.anyOf[1]!.$id, undefined)
// Assert.equal(S.$id, 'S')
// })
// it('Should retain cloned $id for wrapped Recursive 1', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Object({
// x: Type.Recursive(
// (Self) =>
// Type.Object({
// self: Type.Optional(Self),
// }),
// { $id: 'RecursiveClone' },
// ),
// })
// Assert.equal(T.properties.x.$id, 'RecursiveClone')
// Assert.equal(S.$id, 'S')
// })
// it('Should retain cloned $id for wrapped Recursive 2', () => {
// const S = Type.String({ $id: 'S' })
// const T = Type.Tuple([
// Type.Recursive(
// (Self) =>
// Type.Object({
// self: Type.Optional(Self),
// }),
// { $id: 'RecursiveClone' },
// ),
// ])
// Assert.equal(T.items![0].$id, 'RecursiveClone')
// Assert.equal(S.$id, 'S')
// })
// })

View File

@@ -0,0 +1 @@
import './clone'

View File

@@ -0,0 +1,95 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Any', () => {
it('Should extend Any', () => {
type T = any extends any ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = any extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = any extends string ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.String())
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Boolean', () => {
type T = any extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Number', () => {
type T = any extends number ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Number())
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Integer', () => {
type T = any extends number ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Array 1', () => {
type T = any extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Array 2', () => {
type T = any extends Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Array(Type.String()))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Tuple', () => {
type T = any extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Object 1', () => {
type T = any extends object ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Object 2', () => {
type T = any extends {} ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Object 3', () => {
type T = any extends { a: number } ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Object({ a: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Union 1', () => {
type T = any extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Union 2', () => {
type T = any extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Union([Type.Any(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = any extends null ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Null())
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Undefined', () => {
type T = any extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Void', () => {
type T = any extends void ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Void())
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Date', () => {
type T = any extends Date ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Date())
Assert.IsEqual(R, ExtendsResult.Union)
})
})

View File

@@ -0,0 +1,264 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Array', () => {
// ----------------------------------------------
// Generic Varying
// ----------------------------------------------
it('Should extend Array Varying 1', () => {
type T = Array<any> extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Array Varying 2', () => {
type T = Array<string> extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Array Varying 3', () => {
type T = Array<any> extends Array<string> ? 1 : 2 // 1
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Array(Type.String()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Array Varying 4', () => {
type T = Array<number> extends Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Number()), Type.Array(Type.String()))
Assert.IsEqual(R, ExtendsResult.False)
})
// ----------------------------------------------
// Any
// ----------------------------------------------
it('Should extend Any', () => {
type T = Array<any> extends any ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = Array<any> extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = Array<any> extends string ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = Array<any> extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = Array<any> extends number ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = Array<any> extends number ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 1', () => {
type T = Array<any> extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Array 2', () => {
type T = Array<string> extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Array 3', () => {
type T = Array<any> extends Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Tuple', () => {
type T = Array<any> extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = Array<any> extends object ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = Array<any> extends {} ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 3', () => {
type T = Array<any> extends { a: number } ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Object({ a: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 4', () => {
type T = Array<any> extends { length: '1' } ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Object({ length: Type.Literal('1') }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 5', () => {
type T = Array<any> extends { length: number } ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Object({ length: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 1', () => {
type T = Array<any> extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = Array<any> extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = Array<any> extends any | Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Union([Type.Any(), Type.Array(Type.Any())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 4', () => {
type T = Array<string> extends any | Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.Any())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 5', () => {
type T = Array<any> extends any | Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Union([Type.Any(), Type.Array(Type.String())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = Array<any> extends null ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = Array<any> extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.Any()), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
// ----------------------------------------------
// Constrained
// ----------------------------------------------
it('Should extend constrained Any', () => {
type T = Array<string> extends any ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Unknown', () => {
type T = Array<string> extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained String', () => {
type T = Array<string> extends string ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Boolean', () => {
type T = Array<string> extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Number', () => {
type T = Array<string> extends number ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Integer', () => {
type T = Array<string> extends number ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Array 1', () => {
type T = Array<string> extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Array 2', () => {
type T = Array<string> extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Array 3', () => {
type T = Array<string> extends Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Tuple', () => {
type T = Array<string> extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Object 1', () => {
type T = Array<string> extends object ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Object 2', () => {
type T = Array<string> extends {} ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Object 3', () => {
type T = Array<string> extends { a: number } ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Object({ a: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Object 4', () => {
type T = Array<string> extends { length: '1' } ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Object({ length: Type.Literal('1') }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Object 5', () => {
type T = Array<string> extends { length: number } ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Object({ length: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Union 1', () => {
type T = Array<string> extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Null(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Union 2', () => {
type T = Array<string> extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Any(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Union 3', () => {
type T = Array<string> extends any | Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.Any())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Union 4', () => {
type T = Array<string> extends any | Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.Any())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Union 5', () => {
type T = Array<string> extends any | Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.String())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Null', () => {
type T = Array<string> extends null ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Undefined', () => {
type T = Array<string> extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Void', () => {
type T = Array<string> extends void ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = Array<string> extends Date ? 1 : 2
const R = ExtendsCheck(Type.Array(Type.String()), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,71 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/AsyncIterator', () => {
// ----------------------------------------------
// Generic Varying
// ----------------------------------------------
it('Should extend AsyncIterator 1', () => {
type T = AsyncIterableIterator<any> extends AsyncIterableIterator<any> ? 1 : 2
const R = ExtendsCheck(Type.AsyncIterator(Type.Any()), Type.AsyncIterator(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend AsyncIterator 2', () => {
type T = AsyncIterableIterator<string> extends AsyncIterableIterator<string> ? 1 : 2
const R = ExtendsCheck(Type.AsyncIterator(Type.String()), Type.AsyncIterator(Type.String()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend AsyncIterator 3', () => {
type T = AsyncIterableIterator<'hello'> extends AsyncIterableIterator<string> ? 1 : 2
const R = ExtendsCheck(Type.AsyncIterator(Type.Literal('hello')), Type.AsyncIterator(Type.String()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend AsyncIterator 4', () => {
type T = AsyncIterableIterator<string> extends AsyncIterableIterator<'hello'> ? 1 : 2
const R = ExtendsCheck(Type.AsyncIterator(Type.String()), Type.AsyncIterator(Type.Literal('hello')))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend AsyncIterator 5', () => {
type T = AsyncIterableIterator<string> extends AsyncIterableIterator<'hello' | number> ? 1 : 2
const R = ExtendsCheck(Type.AsyncIterator(Type.String()), Type.AsyncIterator(Type.Union([Type.Literal('hello'), Type.Number()])))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend AsyncIterator 6', () => {
type T = AsyncIterableIterator<'hello' | number> extends AsyncIterableIterator<string> ? 1 : 2
const R = ExtendsCheck(Type.AsyncIterator(Type.Union([Type.Literal('hello'), Type.Number()])), Type.AsyncIterator(Type.String()))
Assert.IsEqual(R, ExtendsResult.False)
})
// --------------------------------------------------------------------
// Structural
// --------------------------------------------------------------------
it('Should extends Any 1', () => {
type T = AsyncIterableIterator<number> extends any ? 1 : 2
const R = ExtendsCheck(Type.AsyncIterator(Type.Number()), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extends Any 2', () => {
type T = any extends AsyncIterableIterator<number> ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.AsyncIterator(Type.Number()))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extends Unknown 1', () => {
type T = AsyncIterableIterator<number> extends unknown ? 1 : 2
const R = ExtendsCheck(Type.AsyncIterator(Type.Number()), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extends Unknown 2', () => {
type T = unknown extends AsyncIterableIterator<number> ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.AsyncIterator(Type.Number()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extends Never 1', () => {
type T = AsyncIterableIterator<number> extends never ? 1 : 2
const R = ExtendsCheck(Type.AsyncIterator(Type.Number()), Type.Never())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extends Never 2', () => {
type T = never extends AsyncIterableIterator<number> ? 1 : 2
const R = ExtendsCheck(Type.Never(), Type.AsyncIterator(Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
})

View File

@@ -0,0 +1,100 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/BigInt', () => {
it('Should extend Any', () => {
type T = bigint extends any ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = bigint extends unknown ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = bigint extends string ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = bigint extends boolean ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = bigint extends number ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = bigint extends number ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = bigint extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = bigint extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = bigint extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = bigint extends {} ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = bigint extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Object({ a: Type.Literal(10) }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = bigint extends number | string ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = bigint extends any | number ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = bigint extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 4', () => {
type T = bigint extends boolean | bigint ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Union([Type.Boolean(), Type.BigInt()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = bigint extends null ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = bigint extends undefined ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = bigint extends undefined ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = bigint extends Date ? 1 : 2
const R = ExtendsCheck(Type.BigInt(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,90 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Boolean', () => {
it('Should extend Any', () => {
type T = boolean extends any ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = boolean extends string ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = boolean extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Number', () => {
type T = boolean extends number ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = boolean extends number ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = boolean extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = boolean extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = boolean extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = boolean extends {} ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = boolean extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = boolean extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = boolean extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = boolean extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = boolean extends null ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = boolean extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = boolean extends void ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = boolean extends Date ? 1 : 2
const R = ExtendsCheck(Type.Boolean(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,210 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Constructor', () => {
it('Should extend Function', () => {
type T = (new () => number) extends () => number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Function([], Type.Number()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Constructor 1', () => {
type T = (new () => number) extends new () => number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Constructor([], Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 2', () => {
type T = (new () => any) extends new () => number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Any()), Type.Constructor([], Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 3', () => {
type T = (new () => number) extends new () => any ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Any()), Type.Constructor([], Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 4', () => {
type T = (new (a: number) => number) extends new () => any ? 1 : 2
const R = ExtendsCheck(Type.Constructor([Type.Number()], Type.Number()), Type.Constructor([], Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Constructor 5', () => {
type T = (new (a: number | string) => number) extends new (a: number) => number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([Type.Union([Type.Number(), Type.String()])], Type.Number()), Type.Constructor([Type.Number()], Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 6', () => {
type T = (new (a: number) => number) extends new (a: number | string) => any ? 1 : 2
const R = ExtendsCheck(Type.Constructor([Type.Number()], Type.Number()), Type.Constructor([Type.Union([Type.Number(), Type.String()])], Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Constructor 7', () => {
type T = (new (a: number, b: number) => number) extends new (a: number) => number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([Type.Number(), Type.Number()], Type.Number()), Type.Constructor([Type.Number()], Type.Number()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Constructor 8', () => {
type T = (new (a: number) => number) extends new (a: number, b: number) => number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([Type.Number()], Type.Number()), Type.Constructor([Type.Number(), Type.Number()], Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 9', () => {
type T = (new () => number) extends new () => any ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Constructor([], Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 9', () => {
type T = (new () => any) extends new () => number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Any()), Type.Constructor([], Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 10', () => {
type T = (new () => Array<any>) extends new () => object ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Array(Type.Any())), Type.Constructor([], Type.Object({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 11', () => {
type T = (new () => Array<string>) extends new () => object ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Array(Type.String())), Type.Constructor([], Type.Object({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 12', () => {
type T = (new () => object) extends new () => Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Object({})), Type.Constructor([], Type.Array(Type.Any())))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Constructor 13', () => {
type T = (new (a: unknown) => number) extends new (a: any) => number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([Type.Unknown()], Type.Number({})), Type.Constructor([Type.Any()], Type.Number({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 14', () => {
type T = (new (a: any) => number) extends new (a: unknown) => number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([Type.Any()], Type.Number({})), Type.Constructor([Type.Unknown()], Type.Number({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 15', () => {
type T = (new () => any) extends new () => unknown ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Any({})), Type.Constructor([], Type.Unknown({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Constructor 16', () => {
type T = (new () => unknown) extends new () => any ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Unknown({})), Type.Constructor([], Type.Any({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Any', () => {
type T = (new () => number) extends any ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = (new () => number) extends string ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = (new () => number) extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = (new () => number) extends number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = (new () => number) extends number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 1', () => {
type T = (new () => number) extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 2', () => {
type T = (new () => number) extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 3', () => {
type T = (new () => number) extends Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = (new () => number) extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = (() => number) extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = (new () => number) extends object ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = (new () => number) extends {} ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 3', () => {
type T = (new () => number) extends { a: number } ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Object({ a: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 4', () => {
type T = (new () => number) extends { length: '1' } ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Object({ length: Type.Literal('1') }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = (new () => number) extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Union([Type.Null(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = (new () => number) extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = (new () => number) extends any | Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 4', () => {
type T = (new () => number) extends any | Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 5', () => {
type T = (new () => number) extends any | Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.String())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = (new () => number) extends null ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = (new () => number) extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = (new () => number) extends void ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = (new () => number) extends Date ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,95 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Date', () => {
it('Should extend Any', () => {
type T = Date extends any ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = Date extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = Date extends string ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = Date extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = Date extends number ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = Date extends number ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = Date extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = Date extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = Date extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = Date extends {} ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = Date extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = Date extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = Date extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = Date extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null', () => {
type T = Date extends null ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = Date extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = Date extends void ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = Date extends Date ? 1 : 2
const R = ExtendsCheck(Type.Date(), Type.Date())
Assert.IsEqual(R, ExtendsResult.True)
})
})

View File

@@ -0,0 +1,210 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Function', () => {
it('Should extend Constructor 1', () => {
type T = (() => number) extends new () => number ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Constructor([], Type.Number()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Function 1', () => {
type T = (() => number) extends () => number ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Function([], Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 2', () => {
type T = (() => any) extends () => number ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Any()), Type.Function([], Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 3', () => {
type T = (() => number) extends () => any ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Any()), Type.Function([], Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 4', () => {
type T = ((a: number) => number) extends () => any ? 1 : 2
const R = ExtendsCheck(Type.Function([Type.Number()], Type.Number()), Type.Function([], Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Function 5', () => {
type T = ((a: number | string) => number) extends (a: number) => number ? 1 : 2
const R = ExtendsCheck(Type.Function([Type.Union([Type.Number(), Type.String()])], Type.Number()), Type.Function([Type.Number()], Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 6', () => {
type T = ((a: number) => number) extends (a: number | string) => any ? 1 : 2
const R = ExtendsCheck(Type.Function([Type.Number()], Type.Number()), Type.Function([Type.Union([Type.Number(), Type.String()])], Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Function 7', () => {
type T = ((a: number, b: number) => number) extends (a: number) => number ? 1 : 2
const R = ExtendsCheck(Type.Function([Type.Number(), Type.Number()], Type.Number()), Type.Function([Type.Number()], Type.Number()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Function 8', () => {
type T = ((a: number) => number) extends (a: number, b: number) => number ? 1 : 2
const R = ExtendsCheck(Type.Function([Type.Number()], Type.Number()), Type.Function([Type.Number(), Type.Number()], Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 9', () => {
type T = (() => number) extends () => any ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Function([], Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 9', () => {
type T = (() => any) extends () => number ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Any()), Type.Function([], Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 10', () => {
type T = (() => Array<any>) extends () => object ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Array(Type.Any())), Type.Function([], Type.Object({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 11', () => {
type T = (() => Array<string>) extends () => object ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Array(Type.String())), Type.Function([], Type.Object({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 12', () => {
type T = (() => object) extends () => Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Object({})), Type.Function([], Type.Array(Type.Any())))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Function 13', () => {
type T = ((a: unknown) => number) extends (a: any) => number ? 1 : 2
const R = ExtendsCheck(Type.Function([Type.Unknown()], Type.Number({})), Type.Function([Type.Any()], Type.Number({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 14', () => {
type T = ((a: any) => number) extends (a: unknown) => number ? 1 : 2
const R = ExtendsCheck(Type.Function([Type.Any()], Type.Number({})), Type.Function([Type.Unknown()], Type.Number({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 15', () => {
type T = (() => any) extends () => unknown ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Any({})), Type.Function([], Type.Unknown({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Function 16', () => {
type T = (() => unknown) extends () => any ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Unknown({})), Type.Function([], Type.Any({})))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Any', () => {
type T = (() => number) extends any ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = (() => number) extends string ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = (() => number) extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = (() => number) extends number ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = (() => number) extends number ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 1', () => {
type T = (() => number) extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 2', () => {
type T = (() => number) extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 3', () => {
type T = (() => number) extends Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = (() => number) extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = (() => number) extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = (() => number) extends object ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = (() => number) extends {} ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 3', () => {
type T = (() => number) extends { a: number } ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Object({ a: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 4', () => {
type T = (() => number) extends { length: '1' } ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Object({ length: Type.Literal('1') }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 5', () => {
type T = (() => number) extends { length: number } ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Object({ length: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 1', () => {
type T = (() => number) extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Union([Type.Null(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = (() => number) extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = (() => number) extends any | Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 4', () => {
type T = (() => number) extends any | Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 5', () => {
type T = (() => number) extends any | Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.String())]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = (() => number) extends null ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = (() => number) extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = (() => number) extends Date ? 1 : 2
const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,27 @@
import './any'
import './array'
import './async-iterator'
import './bigint'
import './boolean'
import './constructor'
import './date'
import './function'
import './integer'
import './iterator'
import './literal'
import './not'
import './null'
import './number'
import './object'
import './promise'
import './record'
import './regexp'
import './string'
import './symbol'
import './template-literal'
import './tuple'
import './uint8array'
import './undefined'
import './union'
import './unknown'
import './void'

View File

@@ -0,0 +1,95 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Integer', () => {
it('Should extend Any', () => {
type T = number extends any ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = number extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = number extends string ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = number extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = number extends number ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Number())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Integer', () => {
type T = number extends number ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Array', () => {
type T = number extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = number extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = number extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = number extends {} ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = number extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Object({ a: Type.Literal(10) }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = number extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = number extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = number extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = number extends null ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = number extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = number extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Integer(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = number extends Date ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,71 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Iterator', () => {
// ----------------------------------------------
// Generic Varying
// ----------------------------------------------
it('Should extend Iterator 1', () => {
type T = IterableIterator<any> extends IterableIterator<any> ? 1 : 2
const R = ExtendsCheck(Type.Iterator(Type.Any()), Type.Iterator(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Iterator 2', () => {
type T = IterableIterator<string> extends IterableIterator<string> ? 1 : 2
const R = ExtendsCheck(Type.Iterator(Type.String()), Type.Iterator(Type.String()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Iterator 3', () => {
type T = IterableIterator<'hello'> extends IterableIterator<string> ? 1 : 2
const R = ExtendsCheck(Type.Iterator(Type.Literal('hello')), Type.Iterator(Type.String()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Iterator 4', () => {
type T = IterableIterator<string> extends IterableIterator<'hello'> ? 1 : 2
const R = ExtendsCheck(Type.Iterator(Type.String()), Type.Iterator(Type.Literal('hello')))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Iterator 5', () => {
type T = IterableIterator<string> extends IterableIterator<'hello' | number> ? 1 : 2
const R = ExtendsCheck(Type.Iterator(Type.String()), Type.Iterator(Type.Union([Type.Literal('hello'), Type.Number()])))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Iterator 6', () => {
type T = IterableIterator<'hello' | number> extends IterableIterator<string> ? 1 : 2
const R = ExtendsCheck(Type.Iterator(Type.Union([Type.Literal('hello'), Type.Number()])), Type.Iterator(Type.String()))
Assert.IsEqual(R, ExtendsResult.False)
})
// --------------------------------------------------------------------
// Structural
// --------------------------------------------------------------------
it('Should extends Any 1', () => {
type T = IterableIterator<number> extends any ? 1 : 2
const R = ExtendsCheck(Type.Iterator(Type.Number()), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extends Any 2', () => {
type T = any extends IterableIterator<number> ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Iterator(Type.Number()))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extends Unknown 1', () => {
type T = IterableIterator<number> extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Iterator(Type.Number()), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extends Unknown 2', () => {
type T = unknown extends IterableIterator<number> ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Iterator(Type.Number()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extends Never 1', () => {
type T = IterableIterator<number> extends never ? 1 : 2
const R = ExtendsCheck(Type.Iterator(Type.Number()), Type.Never())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extends Never 2', () => {
type T = never extends IterableIterator<number> ? 1 : 2
const R = ExtendsCheck(Type.Never(), Type.Iterator(Type.Number()))
Assert.IsEqual(R, ExtendsResult.True)
})
})

View File

@@ -0,0 +1,264 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Literal', () => {
// -------------------------------------------------------------------
// String Literal
// -------------------------------------------------------------------
it('Should extend Any (String)', () => {
type T = 'hello' extends any ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown (String)', () => {
type T = 'hello' extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String (String)', () => {
type T = 'hello' extends string ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.String())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Boolean (String)', () => {
type T = 'hello' extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number (String)', () => {
type T = 'hello' extends number ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer (String)', () => {
type T = 'hello' extends number ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array (String)', () => {
type T = 'hello' extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple (String)', () => {
type T = 'hello' extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1 (String)', () => {
type T = 'hello' extends {} ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2 (String)', () => {
type T = 'hello' extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1 (String)', () => {
type T = 'hello' extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2 (String)', () => {
type T = 'hello' extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3 (String)', () => {
type T = 'hello' extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null (String)', () => {
type T = 'hello' extends null ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined (String)', () => {
type T = 'hello' extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
// -------------------------------------------------------------------
// Number Literal
// -------------------------------------------------------------------
it('Should extend Any (Number)', () => {
type T = 10 extends any ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown (Number)', () => {
type T = 10 extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String (Number)', () => {
type T = 10 extends string ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean (Number)', () => {
type T = 10 extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number (Number)', () => {
type T = 10 extends number ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Number())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Integer (Number)', () => {
type T = 10 extends number ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Integer())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Array (Number)', () => {
type T = 10 extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple (Number)', () => {
type T = 10 extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1 (Number)', () => {
type T = 10 extends {} ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2 (Number)', () => {
type T = 10 extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1 (Number)', () => {
type T = 10 extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2 (Number)', () => {
type T = 10 extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3 (Number)', () => {
type T = 10 extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null (Number)', () => {
type T = 10 extends null ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined (Number)', () => {
type T = 10 extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
// -------------------------------------------------------------------
// Boolean Literal
// -------------------------------------------------------------------
it('Should extend Any (Boolean)', () => {
type T = true extends any ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown (Boolean)', () => {
type T = true extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String (Boolean)', () => {
type T = true extends string ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean (Boolean)', () => {
type T = true extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Number (Boolean)', () => {
type T = true extends number ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer (Boolean)', () => {
type T = true extends number ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array (Boolean)', () => {
type T = true extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple (Boolean)', () => {
type T = true extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record 1', () => {
type T = 'hello' extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Literal('hello'), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 2', () => {
type T = 10 extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Literal(10), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record 3', () => {
type T = true extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1 (Boolean)', () => {
type T = true extends {} ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2 (Boolean)', () => {
type T = true extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1 (Boolean)', () => {
type T = true extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2 (Boolean)', () => {
type T = true extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3 (Boolean)', () => {
type T = true extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null (Boolean)', () => {
type T = true extends null ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined (Boolean)', () => {
type T = true extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = true extends void ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = true extends Date ? 1 : 2
const R = ExtendsCheck(Type.Literal(true), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,144 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
// ---------------------------------------------------------------------------
// Note: Not is equivalent to Unknown with the exception of nested negation.
// ---------------------------------------------------------------------------
describe('type/extends/Not', () => {
// -------------------------------------------------------------------------
// Issue: type T = number extends not number ? true : false // true
// type T = number extends unknown ? true : false // true
//
// TypeScript does not support type negation. The best TypeBox can do is
// treat "not" as "unknown". From this standpoint, the extends assignability
// check needs to return true for the following case to keep TypeBox aligned
// with TypeScript static inference.
// -------------------------------------------------------------------------
it('Should extend with unknown assignability check', () => {
const A = Type.Number()
const B = Type.Not(Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True) // we would expect false
})
// ---------------------------------------------------------------------------
// Nested
// ---------------------------------------------------------------------------
it('Should extend with nested negation', () => {
const T1 = Type.String()
const T2 = Type.Not(T1)
const T3 = Type.Not(T2)
const T4 = Type.Not(T3)
const T5 = Type.Not(T4)
const R1 = ExtendsCheck(T1, Type.String())
const R2 = ExtendsCheck(T2, Type.String())
const R3 = ExtendsCheck(T3, Type.String())
const R4 = ExtendsCheck(T4, Type.String())
const R5 = ExtendsCheck(T5, Type.String())
Assert.IsEqual(R1, ExtendsResult.True)
Assert.IsEqual(R2, ExtendsResult.False)
Assert.IsEqual(R3, ExtendsResult.True)
Assert.IsEqual(R4, ExtendsResult.False)
Assert.IsEqual(R5, ExtendsResult.True)
})
// ---------------------------------------------------------------------------
// Not as Unknown Tests
// ---------------------------------------------------------------------------
it('Should extend Any', () => {
type T = unknown extends any ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = unknown extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = unknown extends string ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = unknown extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = unknown extends number ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = unknown extends number ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 1', () => {
type T = unknown extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 2', () => {
type T = unknown extends Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Array(Type.String()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = unknown extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = unknown extends {} ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 2', () => {
type T = unknown extends { a: number } ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Object({ a: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = unknown extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = unknown extends any | number ? 1 : 2 // 1
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Union([Type.Any(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = unknown extends unknown | number ? 1 : 2 // 1
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Union([Type.Unknown(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 4', () => {
type T = unknown extends unknown | any ? 1 : 2 // 1
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Union([Type.Unknown(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = unknown extends null ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = unknown extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = unknown extends void ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = unknown extends Date ? 1 : 2
const R = ExtendsCheck(Type.Not(Type.Number()), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,100 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Null', () => {
it('Should extend Any', () => {
type T = null extends any ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = null extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = null extends string ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = null extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = null extends number ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = null extends number ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = null extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = null extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = null extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = null extends {} ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 2', () => {
type T = null extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 3', () => {
type T = null extends object ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = null extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = null extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = null extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null', () => {
type T = null extends null ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Null())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Undefined', () => {
type T = null extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = null extends void ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = null extends Date ? 1 : 2
const R = ExtendsCheck(Type.Null(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,95 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Number', () => {
it('Should extend Any', () => {
type T = number extends any ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = number extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = number extends string ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = number extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = number extends number ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Number())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Integer', () => {
type T = number extends number ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Array', () => {
type T = number extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = number extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = number extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = number extends {} ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = number extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = number extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = number extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = number extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = number extends null ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = number extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = number extends void ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = number extends Date ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,227 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Object', () => {
// ----------------------------------------------------------
// Object
// ----------------------------------------------------------
it('Should extend Object 1', () => {
type T = { x: number; y: number } extends { x: number } ? 1 : 2
const A = Type.Object({ x: Type.Number(), y: Type.Number() })
const B = Type.Object({ x: Type.Number() })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = { x: number } extends { x: number; y: number } ? 1 : 2
const A = Type.Object({ x: Type.Number() })
const B = Type.Object({ x: Type.Number(), y: Type.Number() })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 3', () => {
type T = { x: number; y: string } extends { x: number } ? 1 : 2
const A = Type.Object({ x: Type.Number(), y: Type.String() })
const B = Type.Object({ x: Type.Number() })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 4', () => {
type T = { x: number } extends { x: number; y: string } ? 1 : 2
const A = Type.Object({ x: Type.Number() })
const B = Type.Object({ x: Type.Number(), y: Type.String() })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 5', () => {
type T = { x: number | string } extends { x: number } ? 1 : 2
const A = Type.Object({ x: Type.Union([Type.Number(), Type.String()]) })
const B = Type.Object({ x: Type.Number() })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 6', () => {
type T = { x: number } extends { x: number | string } ? 1 : 2
const A = Type.Object({ x: Type.Number() })
const B = Type.Object({ x: Type.Union([Type.Number(), Type.String()]) })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
// ----------------------------------------------------------
// Record
// ----------------------------------------------------------
it('Should extend Record 2', () => {
type T = { a: number; b: number } extends Record<string, number> ? 1 : 2
const A = Type.Object({ a: Type.Number(), b: Type.Number() })
const B = Type.Record(Type.String(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 3', () => {
type T = { a: number; b: number } extends Record<number, number> ? 1 : 2
const A = Type.Object({ a: Type.Number(), b: Type.Number() })
const B = Type.Record(Type.Number(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 4', () => {
type T = { a: number; b: number } extends Record<'a' | 'b', number> ? 1 : 2
const A = Type.Object({ a: Type.Number(), b: Type.Number() })
const B = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 5', () => {
type T = { a: number; b: number } extends Record<'a' | 'b', number> ? 1 : 2
const A = Type.Object({ a: Type.Number(), b: Type.Number() })
const B = Type.Record(Type.String(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 6', () => {
type T = { a: number; b: number } extends Record<'a' | 'b', number> ? 1 : 2
const A = Type.Object({ a: Type.Number(), b: Type.Number() })
const B = Type.Record(Type.Number(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
// ----------------------------------------------------------
// Standard
// ----------------------------------------------------------
it('Should extend Any', () => {
type T = { a: number } extends any ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = { a: number } extends string ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = { a: number } extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = { a: number } extends number ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = { a: number } extends number ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = { a: number } extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = { a: number } extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = { a: number } extends {} ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = { a: number } extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Object({ a: Type.Literal(10) }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 3', () => {
type T = { a: number } extends object ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 1', () => {
type T = { a: number } extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Union([Type.Null(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = { a: number } extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = { a: number } extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null', () => {
type T = { a: number } extends null ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = { a: number } extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = { a: number } extends void ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = { a: number } extends Date ? 1 : 2
const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
// ----------------------------------------------------------------
// Optional
// ----------------------------------------------------------------
it('Should extend optional 1', () => {
const A = Type.Object({ a: Type.Number() })
const B = Type.Object({ a: Type.Optional(Type.Number()) })
const C = ExtendsCheck(A, B)
Assert.IsEqual(C, ExtendsResult.True)
})
it('Should extend optional 2', () => {
const A = Type.Object({ a: Type.Number() })
const B = Type.Object({ a: Type.Optional(Type.Number()) })
const C = ExtendsCheck(B, A)
Assert.IsEqual(C, ExtendsResult.False)
})
it('Should extend optional 3', () => {
const A = Type.Object({
x: Type.Optional(Type.Number()),
y: Type.Number(),
})
const B = Type.Object({
y: Type.Number(),
z: Type.Number(),
})
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend optional 4', () => {
const A = Type.Object({
x: Type.Number(),
y: Type.Number(),
})
const B = Type.Object({
y: Type.Number(),
z: Type.Number(),
})
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend optional 5', () => {
const A = Type.Object({
x: Type.Number(),
y: Type.Number(),
})
const B = Type.Object({
y: Type.Number(),
z: Type.Optional(Type.Number()),
})
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
})

View File

@@ -0,0 +1,209 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Promise', () => {
// ----------------------------------------------
// Generic Varying
// ----------------------------------------------
it('Should extend Promise Varying 1', () => {
type T = Promise<any> extends Promise<any> ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Promise(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Promise Varying 2', () => {
type T = Promise<string> extends Promise<any> ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.String()), Type.Promise(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Promise Varying 3', () => {
type T = Promise<any> extends Promise<string> ? 1 : 2 // 1
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Promise(Type.String()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Promise Varying 4', () => {
type T = Promise<number> extends Promise<string> ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Promise(Type.String()))
Assert.IsEqual(R, ExtendsResult.False)
})
// ----------------------------------------------
// Any
// ----------------------------------------------
it('Should extend Any', () => {
type T = Promise<any> extends any ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = Promise<any> extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = Promise<any> extends string ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = Promise<any> extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = Promise<any> extends number ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = Promise<any> extends number ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = Promise<any> extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = Promise<any> extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = Promise<any> extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = Promise<any> extends {} ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = Promise<any> extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 3', () => {
type T = Promise<any> extends object ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 1', () => {
type T = Promise<any> extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = Promise<any> extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = Promise<any> extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null', () => {
type T = Promise<any> extends null ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = Promise<any> extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
// ----------------------------------------------
// Constrained
// ----------------------------------------------
it('Should extend constrained Any', () => {
type T = Promise<number> extends any ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Unknown', () => {
type T = Promise<number> extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained String', () => {
type T = Promise<number> extends string ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Boolean', () => {
type T = Promise<number> extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Number', () => {
type T = Promise<number> extends number ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Integer', () => {
type T = Promise<number> extends number ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Array', () => {
type T = Promise<number> extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Tuple', () => {
type T = Promise<number> extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Object 1', () => {
type T = Promise<number> extends {} ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Object 2', () => {
type T = Promise<number> extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Object 3', () => {
type T = Promise<number> extends object ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Union 1', () => {
type T = Promise<number> extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Union 2', () => {
type T = Promise<number> extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend constrained Union 2', () => {
type T = Promise<number> extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Null', () => {
type T = Promise<number> extends null ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend constrained Undefined', () => {
type T = Promise<number> extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = Promise<number> extends void ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = Promise<number> extends Date ? 1 : 2
const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,199 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Record', () => {
it('Should extend Record 1', () => {
type T = Record<'a' | 'b', number> extends { a: number; b: number } ? 1 : 2
const A = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number())
const B = Type.Object({ a: Type.Number(), b: Type.Number() })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 2', () => {
type T = Record<string, number> extends { a: number; b: number } ? 1 : 2
const A = Type.Record(Type.String(), Type.Number())
const B = Type.Object({ a: Type.Number(), b: Type.Number() })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record 3', () => {
type T = Record<number, number> extends { a: number; b: number } ? 1 : 2
const A = Type.Record(Type.Number(), Type.Number())
const B = Type.Object({ a: Type.Number(), b: Type.Number() })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record 4', () => {
type T = Record<'a' | 'b', number> extends { a: number; b: number } ? 1 : 2
const A = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number())
const B = Type.Object({ a: Type.Number(), b: Type.Number() })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 5', () => {
type T = Record<'a' | 'b', number> extends { a: number; b: number } ? 1 : 2
const A = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number())
const B = Type.Object({ a: Type.Number(), b: Type.Number() })
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 6', () => {
type T = Record<string, number> extends Record<'a' | 'b', number> ? true : false
const A = Type.Record(Type.String(), Type.Number())
const B = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 7', () => {
type T = Record<string, number> extends Record<string, number> ? 1 : 2
const A = Type.Record(Type.String(), Type.Number())
const B = Type.Record(Type.String(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 8', () => {
type T = Record<string, number> extends Record<number, number> ? 1 : 2
const A = Type.Record(Type.String(), Type.Number())
const B = Type.Record(Type.Number(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 9', () => {
type T = Record<number, number> extends Record<'a' | 'b', number> ? 1 : 2
const A = Type.Record(Type.Number(), Type.Number())
const B = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record 10', () => {
type T = Record<number, number> extends Record<string, number> ? 1 : 2
const A = Type.Record(Type.Number(), Type.Number())
const B = Type.Record(Type.String(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 11', () => {
type T = Record<number, number> extends Record<number, number> ? 1 : 2
const A = Type.Record(Type.Number(), Type.Number())
const B = Type.Record(Type.Number(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
// -----
it('Should extend Record 12', () => {
type T = Record<string, number> extends Record<number, number> ? 1 : 2
const A = Type.Record(Type.String(), Type.Number())
const B = Type.Record(Type.Integer(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 13', () => {
type T = Record<number, number> extends Record<'a' | 'b', number> ? 1 : 2
const A = Type.Record(Type.Integer(), Type.Number())
const B = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record 14', () => {
type T = Record<number, number> extends Record<string, number> ? 1 : 2
const A = Type.Record(Type.Integer(), Type.Number())
const B = Type.Record(Type.String(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 15', () => {
type T = Record<number, number> extends Record<number, number> ? 1 : 2
const A = Type.Record(Type.Integer(), Type.Number())
const B = Type.Record(Type.Integer(), Type.Number())
const R = ExtendsCheck(A, B)
Assert.IsEqual(R, ExtendsResult.True)
})
// -------------------------------------------------------------------
// Standard
// -------------------------------------------------------------------
it('Should extend Any', () => {
type T = Record<number, number> extends any ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = Record<number, number> extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = Record<number, number> extends string ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = Record<number, number> extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = Record<number, number> extends number ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = Record<number, number> extends number ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 1', () => {
type T = Record<number, number> extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 2', () => {
type T = Record<number, number> extends Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Array(Type.String()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = Record<number, number> extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 2', () => {
type T = Record<number, number> extends {} ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 3', () => {
type T = Record<number, number> extends { a: number } ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Object({ a: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = Record<number, number> extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = Record<number, number> extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Union([Type.Any(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = Record<number, number> extends null ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = Record<number, number> extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = Record<number, number> extends void ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = Record<number, number> extends Date ? 1 : 2
const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,113 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
// ------------------------------------------------------------------
// Note: RegExp infers as type String
// ------------------------------------------------------------------
describe('type/extends/RegExp', () => {
it('Should extend Any', () => {
type T = string extends any ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = string extends unknown ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = string extends string ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.RegExp(/xyz/))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Boolean', () => {
type T = string extends boolean ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = string extends number ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = string extends number ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = string extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = string extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record 1', () => {
type T = string extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 2', () => {
type T = string extends Record<number, unknown> ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Record(Type.Number(), Type.Unknown()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 3', () => {
type T = string extends Record<number, string> ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Record(Type.Number(), Type.RegExp(/xyz/)))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 4', () => {
type T = string extends Record<number, number> ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Record(Type.Number(), Type.Number()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = string extends {} ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = string extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = number extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Union([Type.Number(), Type.RegExp(/xyz/)]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = number extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = number extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = number extends null ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = number extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = number extends void ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = number extends Date ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,110 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/String', () => {
it('Should extend Any', () => {
type T = string extends any ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = string extends unknown ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = string extends string ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.String())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Boolean', () => {
type T = string extends boolean ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = string extends number ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = string extends number ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = string extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = string extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record 1', () => {
type T = string extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 2', () => {
type T = string extends Record<number, unknown> ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Unknown()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 3', () => {
type T = string extends Record<number, string> ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.String()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 4', () => {
type T = string extends Record<number, number> ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Number()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = string extends {} ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = string extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = number extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = number extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = number extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = number extends null ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = number extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = number extends void ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = number extends Date ? 1 : 2
const R = ExtendsCheck(Type.Number(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,105 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Symbol', () => {
it('Should extend Any', () => {
type T = symbol extends any ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = symbol extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = symbol extends string ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = symbol extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = symbol extends number ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = symbol extends number ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = symbol extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = symbol extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = symbol extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = symbol extends {} ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = symbol extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Object({ a: Type.Literal(10) }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = symbol extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = symbol extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = symbol extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 4', () => {
type T = symbol extends boolean | symbol ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Union([Type.Boolean(), Type.Symbol()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = symbol extends null ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = symbol extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = symbol extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = symbol extends Date ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Symbol', () => {
type T = symbol extends symbol ? 1 : 2
const R = ExtendsCheck(Type.Symbol(), Type.Symbol())
Assert.IsEqual(R, ExtendsResult.True)
})
})

View File

@@ -0,0 +1,161 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/TemplateLiteral', () => {
// -------------------------------------------------------------------
// String Literal 'hello'
// -------------------------------------------------------------------
it('Should extend Any (hello)', () => {
type T = 'hello' extends any ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown (hello)', () => {
type T = 'hello' extends unknown ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String (hello)', () => {
type T = 'hello' extends string ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.String())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Boolean (hello)', () => {
type T = 'hello' extends boolean ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number (hello)', () => {
type T = 'hello' extends number ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer (hello)', () => {
type T = 'hello' extends number ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array (hello)', () => {
type T = 'hello' extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple (hello)', () => {
type T = 'hello' extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1 (hello)', () => {
type T = 'hello' extends {} ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2 (hello)', () => {
type T = 'hello' extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1 (hello)', () => {
type T = 'hello' extends number | string ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2 (hello)', () => {
type T = 'hello' extends any | number ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3 (hello)', () => {
type T = 'hello' extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null (hello)', () => {
type T = 'hello' extends null ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined (hello)', () => {
type T = 'hello' extends undefined ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
// -------------------------------------------------------------------
// String Literal 'hello' | 'world'
// -------------------------------------------------------------------
it('Should extend Any (hello | world)', () => {
type T = 'hello' | 'world' extends any ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown (hello | world)', () => {
type T = 'hello' | 'world' extends unknown ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String (hello | world)', () => {
type T = 'hello' | 'world' extends string ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.String())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Boolean (hello | world)', () => {
type T = 'hello' | 'world' extends boolean ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number (hello | world)', () => {
type T = 'hello' | 'world' extends number ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer (hello | world)', () => {
type T = 'hello' | 'world' extends number ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array (hello | world)', () => {
type T = 'hello' | 'world' extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple (hello | world)', () => {
type T = 'hello' | 'world' extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1 (hello | world)', () => {
type T = 'hello' | 'world' extends {} ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2 (hello | world)', () => {
type T = 'hello' | 'world' extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1 (hello | world)', () => {
type T = 'hello' | 'world' extends number | string ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2 (hello | world)', () => {
type T = 'hello' | 'world' extends any | number ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3 (hello | world)', () => {
type T = 'hello' | 'world' extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null (hello | world)', () => {
type T = 'hello' | 'world' extends null ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined (hello | world)', () => {
type T = 'hello' | 'world' extends undefined ? 1 : 2
const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,160 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Tuple', () => {
it('Should extend Any', () => {
type T = [string, number] extends any ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = [string, number] extends string ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = [string, number] extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = [string, number] extends number ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = [string, number] extends number ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 1', () => {
type T = [string, number] extends Array<any> ? 1 : 2 // 1
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Array 2', () => {
type T = [string, number] extends Array<string> ? 1 : 2 // 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.String()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 3', () => {
type T = [string, number] extends Array<string | number> ? 1 : 2 // 1
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.Union([Type.String(), Type.Number()])))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Array 4', () => {
type T = [string, number] extends Array<string | number | boolean> ? 1 : 2 // 1
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.Union([Type.String(), Type.Number(), Type.Boolean()])))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Tuple 1', () => {
type T = [string, number] extends [string, number] ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.String(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Tuple 2', () => {
type T = [string, number] extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple 3', () => {
type T = [string, any] extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Any()]), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple 4', () => {
type T = [string, number] extends [string, any] ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.String(), Type.Any()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Tuple 5', () => {
type T = [string, unknown] extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Unknown()]), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple 6', () => {
type T = [string, number] extends [string, unknown] ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.String(), Type.Unknown()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Tuple 7', () => {
type T = [] extends [string, number] ? 1 : 2
const R = ExtendsCheck(Type.Tuple([]), Type.Tuple([Type.String(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple 8', () => {
type T = [string, number] extends [] ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record 1', () => {
type T = [string, number] extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 2', () => {
type T = [string, number] extends Record<number, unknown> ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Unknown()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 3', () => {
type T = [string, number] extends Record<number, string> ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.String()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Record 4', () => {
type T = [string, number] extends Record<number, number> ? 1 : 2
const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Number()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = [string, number] extends {} ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = [string, number] extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 3', () => {
type T = [string, number] extends object ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 1', () => {
type T = [string, number] extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = [string, number] extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = [string, number] extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null', () => {
type T = [string, number] extends null ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = [string, number] extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = [string, number] extends void ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = [string, number] extends Date ? 1 : 2
const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,95 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Uint8Array', () => {
it('Should extend Any', () => {
type T = Uint8Array extends any ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = Uint8Array extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = Uint8Array extends string ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = Uint8Array extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = Uint8Array extends number ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = Uint8Array extends number ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = Uint8Array extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = Uint8Array extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Record', () => {
type T = Uint8Array extends Record<number, any> ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Record(Type.Number(), Type.Any()))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 1', () => {
type T = Uint8Array extends {} ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = Uint8Array extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = Uint8Array extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = Uint8Array extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = Uint8Array extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null', () => {
type T = Uint8Array extends null ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = Uint8Array extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = Uint8Array extends void ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = Uint8Array extends Date ? 1 : 2
const R = ExtendsCheck(Type.Uint8Array(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,90 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Undefined', () => {
it('Should extend Any', () => {
type T = undefined extends any ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = undefined extends string ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = undefined extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = undefined extends number ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = undefined extends number ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = undefined extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = undefined extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = undefined extends {} ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 2', () => {
type T = undefined extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 3', () => {
type T = undefined extends object ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = undefined extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = undefined extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = undefined extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null', () => {
type T = undefined extends null ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = undefined extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Void', () => {
type T = undefined extends void ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Void())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Date', () => {
type T = undefined extends Date ? 1 : 2
const R = ExtendsCheck(Type.Undefined(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,135 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Union', () => {
it('Should extend Any', () => {
type T = number | string extends any ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = number | string extends string ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = number | string extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = number | string extends number ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = number | string extends number ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array', () => {
type T = number | string extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = number | string extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = number | string extends {} ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Object({}, { additionalProperties: false }))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Object 2', () => {
type T = number | string extends { a: 10 } ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = number | string extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 2', () => {
type T = number | string extends any | number ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Union([Type.Any(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = number | string extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 4', () => {
type T = any | boolean extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Union 5', () => {
type T = any | string extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Union 6', () => {
type T = any | {} extends {} ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Union 7', () => {
type T = any extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Any(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.Union)
})
it('Should extend Union 8', () => {
type T = unknown | string extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Unknown(), Type.String()]), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 9', () => {
type T = unknown extends boolean | number ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Union([Type.Boolean(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Null', () => {
type T = number | string extends null ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = number | string extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = number | string extends void ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void 2', () => {
type T = number | string | void extends void ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = number | string | void extends Date ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date 2', () => {
type T = Date | number | string | void extends Date ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Date(), Type.Number(), Type.String()]), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend BigInt', () => {
type T = bigint | number | string | void extends Date ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.BigInt(), Type.Number(), Type.String()]), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Symbol', () => {
type T = symbol | number | string | void extends Date ? 1 : 2
const R = ExtendsCheck(Type.Union([Type.Symbol(), Type.Number(), Type.String()]), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,100 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Unknown', () => {
it('Should extend Any', () => {
type T = unknown extends any ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = unknown extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = unknown extends string ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = unknown extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = unknown extends number ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = unknown extends number ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 1', () => {
type T = unknown extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 2', () => {
type T = unknown extends Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Array(Type.String()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = unknown extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = unknown extends {} ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 2', () => {
type T = unknown extends { a: number } ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Object({ a: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = unknown extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = unknown extends any | number ? 1 : 2 // 1
const R = ExtendsCheck(Type.Unknown(), Type.Union([Type.Any(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = unknown extends unknown | number ? 1 : 2 // 1
const R = ExtendsCheck(Type.Unknown(), Type.Union([Type.Unknown(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 4', () => {
type T = unknown extends unknown | any ? 1 : 2 // 1
const R = ExtendsCheck(Type.Unknown(), Type.Union([Type.Unknown(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = unknown extends null ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = unknown extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = unknown extends void ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Void())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Date', () => {
type T = unknown extends Date ? 1 : 2
const R = ExtendsCheck(Type.Unknown(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,105 @@
import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox'
import { Assert } from '../../assert/index'
describe('type/extends/Void', () => {
it('Should extend Any', () => {
type T = void extends any ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Any())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Unknown', () => {
type T = void extends unknown ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Unknown())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend String', () => {
type T = void extends string ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.String())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Boolean', () => {
type T = void extends boolean ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Boolean())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Number', () => {
type T = void extends number ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Number())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Integer', () => {
type T = void extends number ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Integer())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 1', () => {
type T = void extends Array<any> ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Array(Type.Any()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Array 2', () => {
type T = void extends Array<string> ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Array(Type.String()))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Tuple', () => {
type T = void extends [number, number] ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 1', () => {
type T = void extends object ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 2', () => {
type T = void extends {} ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Object({}))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Object 3', () => {
type T = void extends { a: number } ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Object({ a: Type.Number() }))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 1', () => {
type T = void extends number | string ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Union([Type.Number(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Union 2', () => {
type T = void extends any | number ? 1 : 2 // 1
const R = ExtendsCheck(Type.Void(), Type.Union([Type.Any(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 3', () => {
type T = void extends unknown | number ? 1 : 2 // 1
const R = ExtendsCheck(Type.Void(), Type.Union([Type.Unknown(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Union 4', () => {
type T = void extends unknown | any ? 1 : 2 // 1
const R = ExtendsCheck(Type.Void(), Type.Union([Type.Unknown(), Type.String()]))
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Null', () => {
type T = void extends null ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Null())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Undefined', () => {
type T = void extends undefined ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Undefined())
Assert.IsEqual(R, ExtendsResult.False)
})
it('Should extend Void', () => {
type T = void extends void ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Void())
Assert.IsEqual(R, ExtendsResult.True)
})
it('Should extend Date', () => {
type T = void extends Date ? 1 : 2
const R = ExtendsCheck(Type.Void(), Type.Date())
Assert.IsEqual(R, ExtendsResult.False)
})
})

View File

@@ -0,0 +1,3 @@
import './type/index'
import './kind/index'
import './value/index'

View File

@@ -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)
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TArgument', () => {
it('Should guard for TArgument', () => {
const R = KindGuard.IsArgument(Type.Argument(0))
Assert.IsTrue(R)
})
it('Should not guard for TArgument', () => {
const R = KindGuard.IsArgument(null)
Assert.IsFalse(R)
})
})

View File

@@ -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)
})
})

View File

@@ -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)
})
})

View File

@@ -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]))
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TBigInt', () => {
it('Should guard for TBigInt', () => {
const R = KindGuard.IsBigInt(Type.BigInt())
Assert.IsTrue(R)
})
it('Should not guard for TBigInt', () => {
const R = KindGuard.IsBigInt(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TBoolean', () => {
it('Should guard for TBoolean', () => {
const R = KindGuard.IsBoolean(Type.Boolean())
Assert.IsTrue(R)
})
it('Should not guard for TBoolean', () => {
const R = KindGuard.IsBoolean(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,33 @@
import { KindGuard, Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/Capitalize', () => {
it('Should guard for Capitalize 1', () => {
const T = Type.Capitalize(Type.Literal('hello'), { $id: 'hello', foo: 1 })
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'Hello')
Assert.IsEqual(T.$id, 'hello')
Assert.IsEqual(T.foo, 1)
})
it('Should guard for Capitalize 2', () => {
const T = Type.Capitalize(Type.Literal('hello'))
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'Hello')
})
it('Should guard for Capitalize 3', () => {
const T = Type.Capitalize(Type.Union([Type.Literal('hello'), Type.Literal('world')]))
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 'Hello')
Assert.IsEqual(T.anyOf[1].const, 'World')
})
it('Should guard for Capitalize 4', () => {
const T = Type.Capitalize(Type.TemplateLiteral('hello${0|1}'))
Assert.IsTrue(KindGuard.IsTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(Hello0|Hello1)$')
})
it('Should guard for Capitalize 5', () => {
const T = Type.Capitalize(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(0), Type.Literal(1)])]))
Assert.IsTrue(KindGuard.IsTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(Hello0|Hello1)$')
})
})

View File

@@ -0,0 +1,165 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TComposite', () => {
it('Should guard for distinct properties', () => {
const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })])
Assert.IsTrue(KindGuard.IsNumber(T.properties.x))
Assert.IsTrue(KindGuard.IsNumber(T.properties.y))
})
it('Should guard for overlapping properties', () => {
const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() })])
Assert.IsTrue(KindGuard.IsIntersect(T.properties.x))
// @ts-ignore
Assert.IsTrue(KindGuard.IsNumber(T.properties.x.allOf[0]))
// @ts-ignore
Assert.IsTrue(KindGuard.IsNumber(T.properties.x.allOf[1]))
})
it('Should not produce optional property if all properties are not optional', () => {
const T = Type.Composite([Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Number() })])
Assert.IsFalse(KindGuard.IsOptional(T.properties.x))
})
// Note for: https://github.com/sinclairzx81/typebox/issues/419
// Determining if a composite property is optional requires a deep check for all properties gathered during a indexed access
// call. Currently, there isn't a trivial way to perform this check without running into possibly infinite instantiation issues.
// The optional check is only specific to overlapping properties. Singular properties will continue to work as expected. The
// rule is "if all composite properties for a key are optional, then the composite property is optional". Defer this test and
// document as minor breaking change.
//
it('Should produce optional property if all composited properties are optional', () => {
// prettier-ignore
const T = Type.Composite([
Type.Object({ x: Type.Optional(Type.Number()) }),
Type.Object({ x: Type.Optional(Type.Number()) })
])
Assert.IsTrue(KindGuard.IsOptional(T.properties.x))
Assert.IsEqual(T.required, undefined)
})
// prettier-ignore
it('Should produce required property if some composited properties are not optional', () => {
const T = Type.Composite([
Type.Object({ x: Type.Optional(Type.Number()) }),
Type.Object({ x: Type.Number() })
])
Assert.IsFalse(KindGuard.IsOptional(T.properties.x))
Assert.IsTrue(T.required!.includes('x'))
})
// prettier-ignore
it('Should preserve single optional property', () => {
const T = Type.Composite([
Type.Object({ x: Type.Optional(Type.Number()) }),
])
Assert.IsTrue(KindGuard.IsOptional(T.properties.x))
Assert.IsEqual(T.required, undefined)
})
// ----------------------------------------------------------------
// Intersect
// ----------------------------------------------------------------
// prettier-ignore
it('Should composite Intersect 1', () => {
const T = Type.Composite([
Type.Intersect([
Type.Object({ x: Type.Number() }),
Type.Object({ y: Type.Number() }),
]),
Type.Intersect([
Type.Object({ z: Type.Number() }),
])
])
Assert.IsEqual(T, Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number()
}))
})
// prettier-ignore
it('Should composite Intersect 2', () => {
const T = Type.Composite([
Type.Intersect([
Type.Object({ x: Type.Number() }),
Type.Object({ x: Type.Number() }),
]),
Type.Intersect([
Type.Object({ x: Type.Number() }),
])
])
Assert.IsEqual(T, Type.Object({
x: Type.Intersect([Type.Intersect([Type.Number(), Type.Number()]), Type.Number()])
}))
})
// prettier-ignore
it('Should composite Intersect 3', () => {
const T = Type.Composite([
Type.Number(),
Type.Boolean()
])
Assert.IsEqual(T, Type.Object({}))
})
// prettier-ignore
it('Should composite Intersect 4', () => {
const T = Type.Composite([
Type.Number(),
Type.Boolean(),
Type.Object({ x: Type.String() })
])
Assert.IsEqual(T, Type.Object({
x: Type.String()
}))
})
// prettier-ignore
it('Should composite Intersect 5', () => {
const T = Type.Composite([
Type.Object({ x: Type.Optional(Type.String()) }),
Type.Object({ x: Type.String() })
])
Assert.IsEqual(T, Type.Object({
x: Type.Intersect([Type.String(), Type.String()])
}))
})
// prettier-ignore
it('Should composite Intersect 6', () => {
const T = Type.Composite([
Type.Object({ x: Type.Optional(Type.String()) }),
Type.Object({ x: Type.Optional(Type.String()) })
])
Assert.IsEqual(T, Type.Object({
x: Type.Optional(Type.Intersect([Type.String(), Type.String()]))
}))
})
// ----------------------------------------------------------------
// Union
// ----------------------------------------------------------------
// https://github.com/sinclairzx81/typebox/issues/789
// prettier-ignore
it('Should composite Union 1 (non-overlapping)', () => {
const T = Type.Composite([
Type.Union([
Type.Object({ x: Type.Number() }),
Type.Object({ y: Type.Number() }),
]),
Type.Union([
Type.Object({ z: Type.Number() }),
])
])
Assert.IsEqual(T, Type.Object({
z: Type.Number()
}))
})
// https://github.com/sinclairzx81/typebox/issues/789
// prettier-ignore
it('Should composite Union 2 (overlapping)', () => {
const T = Type.Composite([
Type.Union([
Type.Object({ x: Type.Number() }),
Type.Object({ x: Type.Number() }),
]),
Type.Union([
Type.Object({ x: Type.Number() }),
])
])
Assert.IsEqual(T, Type.Object({
x: Type.Intersect([Type.Union([Type.Number(), Type.Number()]), Type.Number()])
}))
})
})

View File

@@ -0,0 +1,33 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TComputed', () => {
// ----------------------------------------------------------------
// Schema
// ----------------------------------------------------------------
it('Should guard for Schema', () => {
const T = Type.Partial(Type.Ref('A'))
Assert.IsTrue(KindGuard.IsComputed(T))
Assert.IsTrue(KindGuard.IsSchema(T))
})
// ----------------------------------------------------------------
// Record
// ----------------------------------------------------------------
it('Should guard for Record 1', () => {
const T = Type.Record(Type.String(), Type.String())
Assert.IsTrue(KindGuard.IsRecord(T))
})
it('Should guard for Record 3', () => {
const T = Type.Record(Type.String(), Type.Ref('A'))
Assert.IsTrue(KindGuard.IsRecord(T))
})
it('Should guard for Record 3', () => {
const T = Type.Record(Type.String(), Type.Partial(Type.Ref('A')))
Assert.IsTrue(KindGuard.IsRecord(T))
})
it('Should guard for Record 4', () => {
const T = Type.Record(Type.Ref('A'), Type.String())
Assert.IsTrue(KindGuard.IsNever(T))
})
})

View File

@@ -0,0 +1,124 @@
import { KindGuard, ValueGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TConstT', () => {
// ----------------------------------------------------------------
// Identity Types
// ----------------------------------------------------------------
it('Should guard for TConst 1', () => {
const T = Type.Const(undefined)
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsUndefined(T))
})
it('Should guard for TConst 2', () => {
const T = Type.Const(null)
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsNull(T))
})
it('Should guard for TConst 3', () => {
const T = Type.Const(Symbol())
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsSymbol(T))
})
it('Should guard for TConst 4', () => {
const T = Type.Const(1 as const)
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 1)
})
it('Should guard for TConst 5', () => {
const T = Type.Const('hello' as const)
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'hello')
})
it('Should guard for TConst 6', () => {
const T = Type.Const(true as const)
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, true)
})
// ----------------------------------------------------------------
// Complex Types
// ----------------------------------------------------------------
it('Should guard for TConst 7', () => {
const T = Type.Const(100n as const)
Assert.IsFalse(KindGuard.IsReadonly(T))
// TS disparity because TLiteral does not support Bigint
Assert.IsTrue(KindGuard.IsBigInt(T))
})
it('Should guard for TConst 8', () => {
const T = Type.Const(new Date())
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsDate(T))
})
it('Should guard for TConst 9', () => {
const T = Type.Const(new Uint8Array())
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsUint8Array(T))
})
it('Should guard for TConst 10', () => {
const T = Type.Const(function () {})
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsFunction(T))
Assert.IsTrue(T.parameters.length === 0)
Assert.IsTrue(KindGuard.IsUnknown(T.returns))
})
it('Should guard for TConst 11', () => {
const T = Type.Const(new (class {})())
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsObject(T))
// Object types that are neither Date or Uint8Array evaluate as empty objects
Assert.IsEqual(T.properties, {})
})
it('Should guard for TConst 12', () => {
const T = Type.Const((function* (): any {})())
const R = ValueGuard.IsIterator((function* (): any {})())
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsAny(T))
})
it('Should guard for TConst 13', () => {
const T = Type.Const((async function* (): any {})())
const R = ValueGuard.IsAsyncIterator((function* (): any {})())
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsAny(T))
})
it('Should guard for TConst 14', () => {
const T = Type.Const({
x: 1,
y: {
z: 2,
},
} as const)
// root
Assert.IsFalse(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsObject(T))
// x
Assert.IsTrue(KindGuard.IsLiteral(T.properties.x))
Assert.IsEqual(T.properties.x.const, 1)
// y
Assert.IsTrue(KindGuard.IsReadonly(T.properties.y))
Assert.IsTrue(KindGuard.IsObject(T.properties.y))
// y.z
Assert.IsTrue(KindGuard.IsReadonly(T.properties.y.properties.z))
Assert.IsTrue(KindGuard.IsLiteral(T.properties.y.properties.z))
Assert.IsEqual(T.properties.y.properties.z.const, 2)
})
it('Should guard for TConst 15', () => {
const T = Type.Const([1, 2, 3] as const)
// root (arrays are always readonly as root)
Assert.IsTrue(KindGuard.IsReadonly(T))
Assert.IsTrue(KindGuard.IsTuple(T))
Assert.IsTrue(T.items?.length === 3)
// 0
Assert.IsFalse(KindGuard.IsReadonly(T.items![0]))
Assert.IsTrue(KindGuard.IsLiteral(T.items![0]))
// 1
Assert.IsFalse(KindGuard.IsReadonly(T.items![1]))
Assert.IsTrue(KindGuard.IsLiteral(T.items![1]))
// 2
Assert.IsFalse(KindGuard.IsReadonly(T.items![2]))
Assert.IsTrue(KindGuard.IsLiteral(T.items![2]))
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TConstructor', () => {
it('Should guard for TConstructor', () => {
const R = KindGuard.IsConstructor(Type.Constructor([], Type.Number()))
Assert.IsTrue(R)
})
it('Should not guard for TConstructor', () => {
const R = KindGuard.IsConstructor(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TDate', () => {
it('Should guard for TDate', () => {
const R = KindGuard.IsDate(Type.Date())
Assert.IsTrue(R)
})
it('Should not guard for TDate', () => {
const R = KindGuard.IsDate(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,143 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TEnum', () => {
// ----------------------------------------------------------------
// Options
// ----------------------------------------------------------------
it('Should guard for Options 1', () => {
const T = Type.Enum({ x: 1 }, { extra: 'hello', $id: 'T' })
Assert.IsEqual(T.extra, 'hello')
Assert.IsEqual(T.$id, 'T')
})
it('Should guard for Options 2', () => {
enum E {
x,
}
const T = Type.Enum(E, { extra: 'hello', $id: 'T' })
Assert.IsEqual(T.extra, 'hello')
Assert.IsEqual(T.$id, 'T')
})
it('Should guard for Options 3', () => {
enum E {}
const T = Type.Enum(E, { extra: 'hello', $id: 'T' })
Assert.IsEqual(T.extra, 'hello')
Assert.IsEqual(T.$id, 'T')
})
it('Should guard for Options 4', () => {
const T = Type.Enum({}, { extra: 'hello', $id: 'T' })
Assert.IsEqual(T.extra, 'hello')
Assert.IsEqual(T.$id, 'T')
})
// ----------------------------------------------------------------
// Empty
// ----------------------------------------------------------------
it('Should guard for Empty 1', () => {
const T = Type.Enum({})
Assert.IsTrue(KindGuard.IsNever(T))
})
it('Should guard for Empty 2', () => {
enum E {}
const T = Type.Enum(E)
Assert.IsTrue(KindGuard.IsNever(T))
})
// ----------------------------------------------------------------
// Enum
// ----------------------------------------------------------------
it('Should guard for TEnum Enum 0', () => {
enum E {}
const T = Type.Enum(E)
Assert.IsTrue(KindGuard.IsNever(T))
})
it('Should guard for TEnum Enum 1', () => {
enum E {
A,
}
const T = Type.Enum(E)
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, E.A)
})
it('Should guard for TEnum Enum 2', () => {
enum E {
A = 1,
B = 2,
C = 3,
}
const T = Type.Enum(E)
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, E.A)
Assert.IsEqual(T.anyOf[1].const, E.B)
Assert.IsEqual(T.anyOf[2].const, E.C)
})
it('Should guard for TEnum Enum 3', () => {
enum E {
A = 'X',
B = 'Y',
C = 'Z',
}
const T = Type.Enum(E)
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, E.A)
Assert.IsEqual(T.anyOf[1].const, E.B)
Assert.IsEqual(T.anyOf[2].const, E.C)
})
it('Should guard for TEnum Enum 4', () => {
enum E {
A = 'X',
B = 'Y',
C = 'X',
}
const T = Type.Enum(E)
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, E.A)
Assert.IsEqual(T.anyOf[1].const, E.B)
Assert.IsEqual(T.anyOf.length, 2)
})
// ----------------------------------------------------------------
// Object Literal
// ----------------------------------------------------------------
it('Should guard for TEnum Object Literal 0', () => {
const T = Type.Enum({})
Assert.IsTrue(KindGuard.IsNever(T))
})
it('Should guard for TEnum Object Literal 1', () => {
const T = Type.Enum({ A: 1 })
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 1)
})
it('Should guard for TEnum Object Literal 2', () => {
const T = Type.Enum({
A: 1,
B: 2,
C: 3,
})
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 1)
Assert.IsEqual(T.anyOf[1].const, 2)
Assert.IsEqual(T.anyOf[2].const, 3)
})
it('Should guard for TEnum Object Literal 3', () => {
const T = Type.Enum({
A: 'X',
B: 'Y',
C: 'Z',
})
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 'X')
Assert.IsEqual(T.anyOf[1].const, 'Y')
Assert.IsEqual(T.anyOf[2].const, 'Z')
})
it('Should guard for TEnum Object Literal 4', () => {
const T = Type.Enum({
A: 'X',
B: 'Y',
C: 'X',
})
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 'X')
Assert.IsEqual(T.anyOf[1].const, 'Y')
Assert.IsEqual(T.anyOf.length, 2)
})
})

View File

@@ -0,0 +1,96 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TExclude', () => {
it('Should exclude string from number', () => {
const T = Type.Exclude(Type.String(), Type.Number())
Assert.IsTrue(KindGuard.IsString(T))
})
it('Should exclude string from string', () => {
const T = Type.Exclude(Type.String(), Type.String())
Assert.IsTrue(KindGuard.IsNever(T))
})
it('Should exclude string | number | boolean from string', () => {
const T = Type.Exclude(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.String())
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsTrue(KindGuard.IsNumber(T.anyOf[0]))
Assert.IsTrue(KindGuard.IsBoolean(T.anyOf[1]))
})
it('Should exclude string | number | boolean from string | boolean', () => {
const T = Type.Exclude(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.Union([Type.String(), Type.Boolean()]))
Assert.IsTrue(KindGuard.IsNumber(T))
})
// ------------------------------------------------------------------------
// TemplateLiteral | TemplateLiteral
// ------------------------------------------------------------------------
it('Should exclude TemplateLiteral | TemplateLiteral 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const T = Type.Exclude(A, B)
Assert.IsTrue(KindGuard.IsNever(T))
})
it('Should exclude TemplateLiteral | TemplateLiteral 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])])
const T = Type.Exclude(A, B)
Assert.IsTrue(['C'].includes(T.const))
})
it('Should exclude TemplateLiteral | TemplateLiteral 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])])
const T = Type.Exclude(A, B)
Assert.IsTrue(['C', 'B'].includes(T.anyOf[0].const))
Assert.IsTrue(['C', 'B'].includes(T.anyOf[1].const))
})
// ------------------------------------------------------------------------
// TemplateLiteral | Union 1
// ------------------------------------------------------------------------
it('Should exclude TemplateLiteral | Union 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])
const T = Type.Exclude(A, B)
Assert.IsTrue(KindGuard.IsNever(T))
})
it('Should exclude TemplateLiteral | Union 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.Union([Type.Literal('A'), Type.Literal('B')])
const T = Type.Exclude(A, B)
Assert.IsTrue(['C'].includes(T.const))
})
it('Should exclude TemplateLiteral | Union 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.Union([Type.Literal('A')])
const T = Type.Exclude(A, B)
Assert.IsTrue(['C', 'B'].includes(T.anyOf[0].const))
Assert.IsTrue(['C', 'B'].includes(T.anyOf[1].const))
})
// ------------------------------------------------------------------------
// Union | TemplateLiteral 1
// ------------------------------------------------------------------------
it('Should exclude Union | TemplateLiteral 1', () => {
const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const T = Type.Exclude(A, B)
Assert.IsTrue(KindGuard.IsNever(T))
})
it('Should exclude Union | TemplateLiteral 1', () => {
const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])])
const T = Type.Exclude(A, B)
Assert.IsTrue(['C'].includes(T.const))
})
it('Should exclude Union | TemplateLiteral 1', () => {
const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])])
const T = Type.Exclude(A, B)
Assert.IsTrue(['C', 'B'].includes(T.anyOf[0].const))
Assert.IsTrue(['C', 'B'].includes(T.anyOf[1].const))
})
it('Should exclude with options', () => {
const A = Type.String()
const B = Type.String()
const T = Type.Exclude(A, B, { foo: 'bar' })
Assert.IsEqual(T.foo, 'bar')
})
})

View File

@@ -0,0 +1,102 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TExtract', () => {
it('Should extract string from number', () => {
const T = Type.Extract(Type.String(), Type.Number())
Assert.IsTrue(KindGuard.IsNever(T))
})
it('Should extract string from string', () => {
const T = Type.Extract(Type.String(), Type.String())
Assert.IsTrue(KindGuard.IsString(T))
})
it('Should extract string | number | boolean from string', () => {
const T = Type.Extract(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.String())
Assert.IsTrue(KindGuard.IsString(T))
})
it('Should extract string | number | boolean from string | boolean', () => {
const T = Type.Extract(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.Union([Type.String(), Type.Boolean()]))
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsTrue(KindGuard.IsString(T.anyOf[0]))
Assert.IsTrue(KindGuard.IsBoolean(T.anyOf[1]))
})
// ------------------------------------------------------------------------
// TemplateLiteral | TemplateLiteral
// ------------------------------------------------------------------------
it('Should extract TemplateLiteral | TemplateLiteral 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const T = Type.Extract(A, B)
Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[0].const))
Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[1].const))
Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[2].const))
})
it('Should extract TemplateLiteral | TemplateLiteral 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])])
const T = Type.Extract(A, B)
Assert.IsTrue(['A', 'B'].includes(T.anyOf[0].const))
Assert.IsTrue(['A', 'B'].includes(T.anyOf[1].const))
})
it('Should extract TemplateLiteral | TemplateLiteral 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])])
const T = Type.Extract(A, B)
Assert.IsTrue(['A'].includes(T.const))
})
// ------------------------------------------------------------------------
// TemplateLiteral | Union 1
// ------------------------------------------------------------------------
it('Should extract TemplateLiteral | Union 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])
const T = Type.Extract(A, B)
Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[0].const))
Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[1].const))
Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[2].const))
})
it('Should extract TemplateLiteral | Union 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.Union([Type.Literal('A'), Type.Literal('B')])
const T = Type.Extract(A, B)
Assert.IsTrue(['A', 'B'].includes(T.anyOf[0].const))
Assert.IsTrue(['A', 'B'].includes(T.anyOf[1].const))
})
it('Should extract TemplateLiteral | Union 1', () => {
const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const B = Type.Union([Type.Literal('A')])
const T = Type.Extract(A, B)
Assert.IsTrue(['A'].includes(T.const))
})
// ------------------------------------------------------------------------
// Union | TemplateLiteral 1
// ------------------------------------------------------------------------
it('Should extract Union | TemplateLiteral 1', () => {
const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])])
const T = Type.Extract(A, B)
Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[0].const))
Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[1].const))
Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[2].const))
})
it('Should extract Union | TemplateLiteral 1', () => {
const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])])
const T = Type.Extract(A, B)
Assert.IsTrue(['A', 'B'].includes(T.anyOf[0].const))
Assert.IsTrue(['A', 'B'].includes(T.anyOf[1].const))
})
it('Should extract Union | TemplateLiteral 1', () => {
const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])
const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])])
const T = Type.Extract(A, B)
Assert.IsTrue(['A'].includes(T.const))
})
it('Should extract with options', () => {
const A = Type.String()
const B = Type.String()
const T = Type.Extract(A, B, { foo: 'bar' })
Assert.IsEqual(T.foo, 'bar')
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TFunction', () => {
it('Should guard for TFunction', () => {
const R = KindGuard.IsFunction(Type.Function([], Type.Number()))
Assert.IsTrue(R)
})
it('Should not guard for TFunction', () => {
const R = KindGuard.IsFunction(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,291 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TImport', () => {
it('Should guard for TImport', () => {
const Module = Type.Module({
A: Type.String(),
})
const A = Module.Import('A')
const N = A.$defs[A.$ref]
Assert.IsTrue(KindGuard.IsImport(A))
Assert.IsTrue(KindGuard.IsString(N))
})
// ----------------------------------------------------------------
// Computed: Options
// ----------------------------------------------------------------
it('Should guard for TImport with Options 1', () => {
const Module = Type.Module({
A: Type.String(),
})
const A = Module.Import('A', { format: 'string' })
const N = A.$defs[A.$ref]
Assert.IsTrue(KindGuard.IsImport(A))
Assert.IsTrue(KindGuard.IsString(N))
Assert.IsTrue(N.format === 'string')
})
it('Should guard for TImport with Options 2', () => {
const Module = Type.Module({
R: Type.Object({ x: Type.Number() }),
A: Type.Ref('R'),
})
const A = Module.Import('A', { test: 'test' })
const N = A.$defs[A.$ref]
Assert.IsTrue(KindGuard.IsImport(A))
Assert.IsTrue(KindGuard.IsRef(N))
Assert.IsTrue(N.test === 'test')
})
it('Should guard for TImport with Options 3', () => {
const Module = Type.Module({
R: Type.Object({ x: Type.Number() }),
A: Type.Partial(Type.Ref('R')),
})
const A = Module.Import('A', { additionalProperties: false })
const N = A.$defs[A.$ref]
Assert.IsTrue(KindGuard.IsImport(A))
Assert.IsTrue(KindGuard.IsObject(N))
Assert.IsTrue(N.additionalProperties === false)
})
// ----------------------------------------------------------------
// Computed: Awaited
// ----------------------------------------------------------------
it('Should compute for Awaited', () => {
const Module = Type.Module({
T: Type.Promise(Type.String()),
R: Type.Awaited(Type.Ref('T')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsString(T.$defs['R']))
})
// ----------------------------------------------------------------
// Computed: Index (Note: Pending Reimplementation of Index)
// ----------------------------------------------------------------
it('Should compute for Index 2', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.String() }),
I: Type.Literal('x'),
R: Type.Index(Type.Ref('T'), Type.Ref('I')) as never, // fail
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R']))
})
// ----------------------------------------------------------------
// Computed: Omit
// ----------------------------------------------------------------
it('Should compute for Omit 1', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.Number() }),
R: Type.Omit(Type.Ref('T'), Type.Literal('x')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.y))
// @ts-ignore
Assert.IsTrue(T.$defs['R'].properties.x === undefined)
})
it('Should compute for Omit 2', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.Number() }),
K: Type.Literal('x'),
R: Type.Omit(Type.Ref('T'), Type.Ref('K')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.y))
// @ts-ignore
Assert.IsTrue(T.$defs['R'].properties.x === undefined)
})
// ----------------------------------------------------------------
// Computed: Partial
// ----------------------------------------------------------------
it('Should compute for Partial', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number() }),
R: Type.Partial(Type.Ref('T')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x))
Assert.IsTrue(KindGuard.IsOptional(T.$defs['R'].properties.x))
})
// ----------------------------------------------------------------
// Computed: Pick
// ----------------------------------------------------------------
it('Should compute for Pick 1', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.Number() }),
R: Type.Pick(Type.Ref('T'), Type.Literal('x')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x))
// @ts-ignore
Assert.IsTrue(T.$defs['R'].properties.y === undefined)
})
it('Should compute for Pick 2', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.Number() }),
K: Type.Literal('x'),
R: Type.Pick(Type.Ref('T'), Type.Ref('K')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x))
// @ts-ignore
Assert.IsTrue(T.$defs['R'].properties.y === undefined)
})
// ----------------------------------------------------------------
// Computed: Record
// ----------------------------------------------------------------
it('Should compute for Record 1', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.String() }),
R: Type.Record(Type.String(), Type.Ref('T')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsRecord(T.$defs['R']))
// note: TRecord<TSchema, TRef<...>> are not computed. Only the Key is
// computed as TypeBox needs to make a deferred call to transform from
// TRecord to TObject for finite keys.
Assert.IsTrue(KindGuard.IsRef(T.$defs['R'].patternProperties['^(.*)$']))
Assert.IsTrue(T.$defs['R'].patternProperties['^(.*)$'].$ref === 'T')
})
it('Should compute for Record 2', () => {
const Module = Type.Module({
T: Type.Number(),
R: Type.Record(Type.Union([Type.Literal('x'), Type.Literal('y')]), Type.Ref('T')),
})
// Retain reference if not computed
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsRef(T.$defs['R'].properties.x))
Assert.IsTrue(KindGuard.IsRef(T.$defs['R'].properties.y))
})
it('Should compute for Record 3', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number() }),
R: Type.Record(Type.Union([Type.Literal('x'), Type.Literal('y')]), Type.Partial(Type.Ref('T'))),
})
// Dereference if computed
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsObject(T.$defs['R'].properties.x))
Assert.IsTrue(KindGuard.IsObject(T.$defs['R'].properties.y))
})
// ----------------------------------------------------------------
// Computed: Required
// ----------------------------------------------------------------
it('Should compute for Required', () => {
const Module = Type.Module({
T: Type.Partial(Type.Object({ x: Type.Number() })),
R: Type.Required(Type.Ref('T')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x))
Assert.IsFalse(KindGuard.IsOptional(T.$defs['R'].properties.x))
})
// ----------------------------------------------------------------
// Computed: KeyOf
// ----------------------------------------------------------------
it('Should compute for KeyOf', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.String() }),
R: Type.KeyOf(Type.Ref('T')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsUnion(T.$defs['R']))
Assert.IsTrue(KindGuard.IsLiteral(T.$defs['R'].anyOf[0]))
Assert.IsTrue(KindGuard.IsLiteral(T.$defs['R'].anyOf[1]))
Assert.IsTrue(T.$defs['R'].anyOf[0].const === 'x')
Assert.IsTrue(T.$defs['R'].anyOf[1].const === 'y')
})
// ----------------------------------------------------------------
// Modifiers: 1
// ----------------------------------------------------------------
it('Should compute for Modifiers 1', () => {
const Module = Type.Module({
T: Type.Object({
x: Type.ReadonlyOptional(Type.Null()),
y: Type.Readonly(Type.Null()),
z: Type.Optional(Type.Null()),
w: Type.Null(),
}),
})
const T = Module.Import('T')
const R = T.$defs[T.$ref]
Assert.IsTrue(KindGuard.IsObject(R))
Assert.IsTrue(KindGuard.IsNull(R.properties.x))
Assert.IsTrue(KindGuard.IsReadonly(R.properties.x))
Assert.IsTrue(KindGuard.IsOptional(R.properties.x))
Assert.IsTrue(KindGuard.IsNull(R.properties.y))
Assert.IsTrue(KindGuard.IsReadonly(R.properties.y))
Assert.IsFalse(KindGuard.IsOptional(R.properties.y))
Assert.IsTrue(KindGuard.IsNull(R.properties.z))
Assert.IsTrue(KindGuard.IsOptional(R.properties.z))
Assert.IsFalse(KindGuard.IsReadonly(R.properties.z))
Assert.IsTrue(KindGuard.IsNull(R.properties.w))
Assert.IsFalse(KindGuard.IsOptional(R.properties.w))
Assert.IsFalse(KindGuard.IsReadonly(R.properties.w))
})
// ----------------------------------------------------------------
// Modifiers: 2
// ----------------------------------------------------------------
it('Should compute for Modifiers 2', () => {
const Module = Type.Module({
T: Type.Object({
x: Type.ReadonlyOptional(Type.Array(Type.Null())),
y: Type.Readonly(Type.Array(Type.Null())),
z: Type.Optional(Type.Array(Type.Null())),
w: Type.Array(Type.Null()),
}),
})
const T = Module.Import('T')
const R = T.$defs[T.$ref]
Assert.IsTrue(KindGuard.IsObject(R))
Assert.IsTrue(KindGuard.IsArray(R.properties.x))
Assert.IsTrue(KindGuard.IsNull(R.properties.x.items))
Assert.IsTrue(KindGuard.IsReadonly(R.properties.x))
Assert.IsTrue(KindGuard.IsOptional(R.properties.x))
Assert.IsTrue(KindGuard.IsArray(R.properties.y))
Assert.IsTrue(KindGuard.IsNull(R.properties.y.items))
Assert.IsTrue(KindGuard.IsReadonly(R.properties.y))
Assert.IsFalse(KindGuard.IsOptional(R.properties.y))
Assert.IsTrue(KindGuard.IsArray(R.properties.z))
Assert.IsTrue(KindGuard.IsNull(R.properties.z.items))
Assert.IsTrue(KindGuard.IsOptional(R.properties.z))
Assert.IsFalse(KindGuard.IsReadonly(R.properties.z))
Assert.IsTrue(KindGuard.IsArray(R.properties.w))
Assert.IsTrue(KindGuard.IsNull(R.properties.w.items))
Assert.IsFalse(KindGuard.IsOptional(R.properties.w))
Assert.IsFalse(KindGuard.IsReadonly(R.properties.w))
})
// ----------------------------------------------------------------
// Modifiers: 3
// ----------------------------------------------------------------
it('Should compute for Modifiers 3', () => {
const Module = Type.Module({
T: Type.Object({
x: Type.Array(Type.Null()),
}),
// Computed Partial
U: Type.Partial(Type.Ref('T')),
})
const T = Module.Import('U')
const R = T.$defs[T.$ref]
Assert.IsTrue(KindGuard.IsObject(R))
Assert.IsTrue(KindGuard.IsArray(R.properties.x))
Assert.IsTrue(KindGuard.IsNull(R.properties.x.items))
Assert.IsTrue(KindGuard.IsOptional(R.properties.x))
})
})

View File

@@ -0,0 +1,54 @@
import './any'
import './argument'
import './array'
import './async-iterator'
import './awaited'
import './bigint'
import './boolean'
import './capitalize'
import './composite'
import './computed'
import './const'
import './constructor'
import './date'
import './enum'
import './exclude'
import './extract'
import './function'
import './import'
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'

View File

@@ -0,0 +1,327 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TIndex', () => {
it('Should Index 1', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
})
const I = Type.Index(T, ['x'])
Assert.IsTrue(KindGuard.IsNumber(I))
})
it('Should Index 2', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
})
const I = Type.Index(T, ['x', 'y'])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsString(I.anyOf[1]))
})
it('Should Index 3', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
})
const I = Type.Index(T, Type.KeyOf(T))
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsString(I.anyOf[1]))
})
it('Should Index 4', () => {
const T = Type.Object({
ab: Type.Number(),
ac: Type.String(),
})
const I = Type.Index(T, Type.TemplateLiteral([Type.Literal('a'), Type.Union([Type.Literal('b'), Type.Literal('c')])]))
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsString(I.anyOf[1]))
})
it('Should Index 5', () => {
const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.String() })])
const I = Type.Index(T, ['x', 'y'])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsString(I.anyOf[1]))
})
it('Should Index 6', () => {
const T = Type.Union([Type.Object({ x: Type.Number() }), Type.Object({ x: Type.String() })])
const I = Type.Index(T, ['x'])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsString(I.anyOf[1]))
})
it('Should Index 7', () => {
const T = Type.Array(Type.Null())
const I = Type.Index(T, Type.Number())
Assert.IsTrue(KindGuard.IsNull(I))
})
it('Should Index 6', () => {
const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')])
const I = Type.Index(T, [0])
Assert.IsTrue(KindGuard.IsLiteralString(I))
Assert.IsEqual(I.const, 'hello')
})
it('Should Index 8', () => {
const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')])
const I = Type.Index(T, [1])
Assert.IsTrue(KindGuard.IsLiteralString(I))
Assert.IsEqual(I.const, 'world')
})
it('Should Index 9', () => {
const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')])
const I = Type.Index(T, [0, 1])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsEqual(I.anyOf[0].const, 'hello')
Assert.IsEqual(I.anyOf[1].const, 'world')
})
it('Should Index 10', () => {
const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')])
const I = Type.Index(T, [1, 0])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsEqual(I.anyOf[0].const, 'world')
Assert.IsEqual(I.anyOf[1].const, 'hello')
})
it('Should Index 11', () => {
const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')])
const I = Type.Index(T, [0, 0, 0, 1])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsEqual(I.anyOf[0].const, 'hello')
Assert.IsEqual(I.anyOf[1].const, 'hello')
Assert.IsEqual(I.anyOf[2].const, 'hello')
Assert.IsEqual(I.anyOf[3].const, 'world')
})
it('Should Index 12', () => {
const T = Type.Tuple([Type.String(), Type.Boolean()])
const I = Type.Index(T, Type.Number())
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsString(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsBoolean(I.anyOf[1]))
})
it('Should Index 13', () => {
const T = Type.Tuple([Type.String()])
const I = Type.Index(T, Type.Number())
Assert.IsTrue(KindGuard.IsString(I))
})
it('Should Index 14', () => {
const T = Type.Tuple([])
const I = Type.Index(T, Type.Number())
Assert.IsTrue(KindGuard.IsNever(I))
})
it('Should Index 15', () => {
const T = Type.Object({
0: Type.Number(),
})
const I = Type.Index(T, Type.Literal(0))
Assert.IsTrue(KindGuard.IsNumber(I))
})
it('Should Index 16', () => {
const T = Type.Object({
0: Type.Number(),
})
const I = Type.Index(T, Type.Literal('0'))
Assert.IsTrue(KindGuard.IsNumber(I))
})
it('Should Index 17', () => {
const T = Type.Object({
'0': Type.Number(),
})
const I = Type.Index(T, Type.Literal(0))
Assert.IsTrue(KindGuard.IsNumber(I))
})
it('Should Index 18', () => {
const T = Type.Object({
'0': Type.Number(),
})
const I = Type.Index(T, Type.Literal('0'))
Assert.IsTrue(KindGuard.IsNumber(I))
})
it('Should Index 19', () => {
const T = Type.Object({
0: Type.Number(),
1: Type.String(),
2: Type.Boolean(),
})
const I = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal(2)]))
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsBoolean(I.anyOf[1]))
})
it('Should Index 20', () => {
const T = Type.Object({
0: Type.Number(),
1: Type.String(),
2: Type.Boolean(),
})
const I = Type.Index(T, Type.BigInt())
Assert.IsTrue(KindGuard.IsNever(I))
})
it('Should Index 21', () => {
const T = Type.Object({
0: Type.Number(),
1: Type.String(),
2: Type.Boolean(),
})
const I = Type.Index(T, Type.Object({}))
Assert.IsTrue(KindGuard.IsNever(I))
})
it('Should Index 22', () => {
const A = Type.Object({ x: Type.Literal('A') })
const B = Type.Object({ x: Type.Literal('B') })
const C = Type.Object({ x: Type.Literal('C') })
const D = Type.Object({ x: Type.Literal('D') })
const T = Type.Intersect([A, B, C, D])
const I = Type.Index(T, ['x'])
Assert.IsTrue(KindGuard.IsIntersect(I))
Assert.IsTrue(KindGuard.IsLiteral(I.allOf[0]))
Assert.IsTrue(KindGuard.IsLiteral(I.allOf[1]))
Assert.IsTrue(KindGuard.IsLiteral(I.allOf[2]))
Assert.IsTrue(KindGuard.IsLiteral(I.allOf[3]))
})
it('Should Index 23', () => {
const A = Type.Object({ x: Type.Literal('A') })
const B = Type.Object({ x: Type.Literal('B') })
const C = Type.Object({ x: Type.Literal('C') })
const D = Type.Object({ x: Type.Literal('D') })
const T = Type.Union([A, B, C, D])
const I = Type.Index(T, ['x'])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsLiteral(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsLiteral(I.anyOf[1]))
Assert.IsTrue(KindGuard.IsLiteral(I.anyOf[2]))
Assert.IsTrue(KindGuard.IsLiteral(I.anyOf[3]))
})
it('Should Index 24', () => {
const A = Type.Object({ x: Type.Literal('A'), y: Type.Number() })
const B = Type.Object({ x: Type.Literal('B') })
const C = Type.Object({ x: Type.Literal('C') })
const D = Type.Object({ x: Type.Literal('D') })
const T = Type.Intersect([A, B, C, D])
const I = Type.Index(T, ['x', 'y'])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsIntersect(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1]))
})
it('Should Index 25', () => {
const A = Type.Object({ x: Type.Literal('A'), y: Type.Number() })
const B = Type.Object({ x: Type.Literal('B'), y: Type.String() })
const C = Type.Object({ x: Type.Literal('C') })
const D = Type.Object({ x: Type.Literal('D') })
const T = Type.Intersect([A, B, C, D])
const I = Type.Index(T, ['x', 'y'])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsIntersect(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsIntersect(I.anyOf[1]))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1].allOf[0]))
Assert.IsTrue(KindGuard.IsString(I.anyOf[1].allOf[1]))
})
it('Should Index 26', () => {
const T = Type.Recursive((This) =>
Type.Object({
x: Type.String(),
y: Type.Number(),
z: This,
}),
)
const I = Type.Index(T, ['x', 'y', 'z'])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsString(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1]))
Assert.IsTrue(KindGuard.IsThis(I.anyOf[2]))
})
it('Should Index 27', () => {
const T = Type.Object({
0: Type.String(),
1: Type.Number(),
})
const I = Type.Index(T, [0, 1])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsString(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1]))
})
it('Should Index 28', () => {
const T = Type.Object({
0: Type.String(),
'1': Type.Number(),
})
const I = Type.Index(T, [0, '1'])
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsString(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1]))
})
it('Should Index 29', () => {
const T = Type.Object({
0: Type.String(),
'1': Type.Number(),
})
const I = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal('1')]))
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsString(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1]))
})
it('Should Index 30', () => {
const T = Type.Object({
0: Type.String(),
'1': Type.Number(),
})
const I = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal(1)]))
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsString(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1]))
// Note: Expect TNever for anyOf[1] but permit for TNumber due to IndexedAccess
// Resolve() which currently cannot differentiate between string and numeric keys
// on the object. This may be resolvable in later revisions, but test for this
// fall-through to ensure case is documented. For review.
})
// --------------------------------------------------------
// Modifier Optional Indexing
// --------------------------------------------------------
it('Should Index 31', () => {
const T = Type.Object({
x: Type.Optional(Type.String()),
y: Type.Number(),
})
const I = Type.Index(T, ['x'])
Assert.IsTrue(KindGuard.IsOptional(I))
Assert.IsTrue(KindGuard.IsString(I))
})
it('Should Index 32', () => {
const T = Type.Object({
x: Type.Optional(Type.String()),
y: Type.Number(),
})
const I = Type.Index(T, ['y'])
Assert.IsFalse(KindGuard.IsOptional(I))
Assert.IsTrue(KindGuard.IsNumber(I))
})
it('Should Index 33', () => {
const T = Type.Object({
x: Type.Optional(Type.String()),
y: Type.Number(),
})
const I = Type.Index(T, ['x', 'y'])
Assert.IsTrue(KindGuard.IsOptional(I))
Assert.IsTrue(KindGuard.IsUnion(I))
Assert.IsTrue(KindGuard.IsString(I.anyOf[0]))
Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1]))
})
it('Should Index 34', () => {
const T = Type.String()
const I = Type.Index(T, ['x'])
Assert.IsTrue(KindGuard.IsNever(I))
})
it('Should Index 35', () => {
const T = Type.Array(Type.String())
const I = Type.Index(T, Type.Number())
Assert.IsTrue(KindGuard.IsString(I))
})
it('Should Index 36', () => {
const T = Type.Array(Type.String())
const I = Type.Index(T, ['[number]'])
Assert.IsTrue(KindGuard.IsString(I))
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TInteger', () => {
it('Should guard for TInteger', () => {
const R = KindGuard.IsInteger(Type.Integer())
Assert.IsTrue(R)
})
it('Should not guard for TInteger', () => {
const R = KindGuard.IsInteger(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,39 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TIntersect', () => {
it('Should guard for TIntersect', () => {
const R = KindGuard.IsIntersect(
Type.Intersect([
Type.Object({
x: Type.Number(),
}),
Type.Object({
y: Type.Number(),
}),
]),
)
Assert.IsTrue(R)
})
it('Should not guard for TIntersect', () => {
const R = KindGuard.IsIntersect(
Type.Union([
Type.Object({
x: Type.Number(),
}),
Type.Object({
y: Type.Number(),
}),
]),
)
Assert.IsFalse(R)
})
it('Should throw for intersected transform types', () => {
const N = Type.Transform(Type.Number())
.Decode((value) => value)
.Encode((value) => value)
Assert.Throws(() => Type.Intersect([N, N]))
})
})

View File

@@ -0,0 +1,16 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TIterator', () => {
it('Should guard for TIterator', () => {
const T = Type.Iterator(Type.Any())
const R = KindGuard.IsIterator(T)
Assert.IsTrue(R)
})
it('Should not guard for TIterator', () => {
const T = null
const R = KindGuard.IsIterator(T)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,76 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TKeyOf', () => {
it('Should KeyOf 1', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.Number(),
})
const K = Type.KeyOf(T)
Assert.IsTrue(KindGuard.IsUnion(K))
Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[0]))
Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[1]))
})
it('Should KeyOf 2', () => {
const T = Type.Recursive((Self) =>
Type.Object({
x: Type.Number(),
y: Type.Array(Self),
}),
)
const K = Type.KeyOf(T)
Assert.IsTrue(KindGuard.IsUnion(K))
Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[0]))
Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[1]))
})
it('Should KeyOf 3', () => {
const T = Type.Intersect([
Type.Object({
x: Type.Number(),
}),
Type.Object({
y: Type.Number(),
}),
])
const K = Type.KeyOf(T)
Assert.IsTrue(KindGuard.IsUnion(K))
Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[0]))
Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[1]))
})
it('Should KeyOf 4', () => {
const T = Type.Union([
Type.Object({
x: Type.Number(),
}),
Type.Object({
y: Type.Number(),
}),
])
const K = Type.KeyOf(T)
Assert.IsTrue(KindGuard.IsNever(K))
})
it('Should KeyOf 5', () => {
const T = Type.Null()
const K = Type.KeyOf(T)
Assert.IsTrue(KindGuard.IsNever(K))
})
it('Should KeyOf 6', () => {
const T = Type.Array(Type.Number())
const K = Type.KeyOf(T)
Assert.IsTrue(KindGuard.IsNumber(K))
})
it('Should KeyOf 7', () => {
const T = Type.Tuple([])
const K = Type.KeyOf(T)
Assert.IsTrue(KindGuard.IsNever(K))
})
it('Should KeyOf 8', () => {
const T = Type.Tuple([Type.Number(), Type.Null()])
const K = Type.KeyOf(T)
Assert.IsTrue(KindGuard.IsUnion(K))
Assert.IsEqual(K.anyOf[0].const, '0')
Assert.IsEqual(K.anyOf[1].const, '1')
})
})

View File

@@ -0,0 +1,13 @@
import { KindGuard, Kind } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TKind', () => {
it('Should guard 1', () => {
const T = { [Kind]: 'Kind' }
Assert.IsTrue(KindGuard.IsKind(T))
})
it('Should guard 2', () => {
const T = {}
Assert.IsFalse(KindGuard.IsKind(T))
})
})

View File

@@ -0,0 +1,18 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TLiteral', () => {
it('Should guard for TLiteral of String', () => {
const R = KindGuard.IsLiteral(Type.Literal('hello'))
Assert.IsTrue(R)
})
it('Should guard for TLiteral of Number', () => {
const R = KindGuard.IsLiteral(Type.Literal(42))
Assert.IsTrue(R)
})
it('Should guard for TLiteral of Boolean', () => {
const R = KindGuard.IsLiteral(Type.Literal(true))
Assert.IsTrue(R)
})
})

View File

@@ -0,0 +1,33 @@
import { KindGuard, Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/Lowercase', () => {
it('Should guard for Lowercase 1', () => {
const T = Type.Lowercase(Type.Literal('HELLO'), { $id: 'hello', foo: 1 })
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'hello')
Assert.IsEqual(T.$id, 'hello')
Assert.IsEqual(T.foo, 1)
})
it('Should guard for Lowercase 2', () => {
const T = Type.Lowercase(Type.Literal('HELLO'))
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'hello')
})
it('Should guard for Lowercase 3', () => {
const T = Type.Lowercase(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD')]))
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 'hello')
Assert.IsEqual(T.anyOf[1].const, 'world')
})
it('Should guard for Lowercase 4', () => {
const T = Type.Lowercase(Type.TemplateLiteral('HELLO${0|1}'))
Assert.IsTrue(KindGuard.IsTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(hello0|hello1)$')
})
it('Should guard for Lowercase 5', () => {
const T = Type.Lowercase(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(0), Type.Literal(1)])]))
Assert.IsTrue(KindGuard.IsTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(hello0|hello1)$')
})
})

View File

@@ -0,0 +1,609 @@
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
// prettier-ignore
describe('guard/kind/Mapped', () => {
it('Should guard mapped 1', () => {
const T = Type.Mapped(Type.Union([
Type.Literal('x'),
Type.Literal('y'),
Type.Literal('z'),
]), _ => Type.Number(), { custom: 1 })
Assert.IsEqual(T, Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number()
}, { custom: 1 }))
})
it('Should guard mapped 2', () => {
const T = Type.Mapped(Type.Union([
Type.Literal('x'),
Type.Literal('y'),
Type.Literal('z'),
]), _ => Type.Number())
Assert.IsEqual(T, Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number()
}))
})
it('Should guard mapped 3', () => {
const T = Type.Mapped(Type.Union([
Type.Literal('x'),
Type.Literal('y'),
Type.Literal('z'),
]), K => K)
Assert.IsEqual(T, Type.Object({
x: Type.Literal('x'),
y: Type.Literal('y'),
z: Type.Literal('z'),
}))
})
it('Should guard mapped 4', () => {
const T = Type.Mapped(Type.TemplateLiteral('${0|1}${0|1}'), K => Type.Number())
Assert.IsEqual(T, Type.Object({
'00': Type.Number(),
'01': Type.Number(),
'10': Type.Number(),
'11': Type.Number(),
}))
})
it('Should guard mapped 5', () => {
const T = Type.Mapped(Type.TemplateLiteral('${a|b}'), X =>
Type.Mapped(Type.TemplateLiteral('${c|d}'), Y =>
Type.Mapped(Type.TemplateLiteral('${e|f}'), Z =>
Type.Tuple([X, Y, Z])
)
)
)
Assert.IsEqual(T, Type.Object({
a: Type.Object({
c: Type.Object({
e: Type.Tuple([Type.Literal("a"), Type.Literal("c"), Type.Literal("e")]),
f: Type.Tuple([Type.Literal("a"), Type.Literal("c"), Type.Literal("f")])
}),
d: Type.Object({
e: Type.Tuple([Type.Literal("a"), Type.Literal("d"), Type.Literal("e")]),
f: Type.Tuple([Type.Literal("a"), Type.Literal("d"), Type.Literal("f")])
}),
}),
b: Type.Object({
c: Type.Object({
e: Type.Tuple([Type.Literal("b"), Type.Literal("c"), Type.Literal("e")]),
f: Type.Tuple([Type.Literal("b"), Type.Literal("c"), Type.Literal("f")])
}),
d: Type.Object({
e: Type.Tuple([Type.Literal("b"), Type.Literal("d"), Type.Literal("e")]),
f: Type.Tuple([Type.Literal("b"), Type.Literal("d"), Type.Literal("f")])
}),
}),
}))
})
it('Should guard mapped 6', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
z: Type.Boolean()
})
const M = Type.Mapped(Type.KeyOf(T), K => K)
Assert.IsEqual(M, Type.Object({
x: Type.Literal('x'),
y: Type.Literal('y'),
z: Type.Literal('z')
}))
})
it('Should guard mapped 7', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
z: Type.Boolean()
})
const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K))
Assert.IsEqual(M, Type.Object({
x: Type.Number(),
y: Type.String(),
z: Type.Boolean()
}))
})
it('Should guard mapped 8', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
z: Type.Boolean()
})
const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K, { custom: 1 }))
Assert.IsEqual(M, Type.Object({
x: Type.Number({ custom: 1 }),
y: Type.String({ custom: 1 }),
z: Type.Boolean({ custom: 1 })
}))
})
// ----------------------------------------------------------------
// Extract
// ----------------------------------------------------------------
it('Should guard mapped 9', () => {
const T = Type.Object({
x: Type.Union([Type.String(), Type.Number(), Type.Boolean()])
})
const M = Type.Mapped(Type.KeyOf(T), K => {
return Type.Extract(Type.Index(T, K), Type.String())
})
Assert.IsEqual(M, Type.Object({
x: Type.String()
}))
})
it('Should guard mapped 10', () => {
const T = Type.Object({
x: Type.Union([Type.String(), Type.Number(), Type.Boolean()])
})
const M = Type.Mapped(Type.KeyOf(T), K => {
return Type.Extract(Type.Index(T, K), Type.Union([
Type.String(),
Type.Number()
]))
})
Assert.IsEqual(M, Type.Object({
x: Type.Union([Type.String(), Type.Number()])
}))
})
it('Should guard mapped 11', () => {
const T = Type.Object({
x: Type.Union([Type.String(), Type.Number(), Type.Boolean()])
})
const M = Type.Mapped(Type.KeyOf(T), K => {
return Type.Extract(Type.Index(T, K), Type.Null())
})
Assert.IsEqual(M, Type.Object({
x: Type.Never()
}))
})
// ----------------------------------------------------------------
// Extends
// ----------------------------------------------------------------
it('Should guard mapped 12', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
z: Type.Boolean()
})
const M = Type.Mapped(Type.KeyOf(T), K => {
return (
Type.Extends(K, Type.Literal('x'), Type.Literal(1),
Type.Extends(K, Type.Literal('y'), Type.Literal(2),
Type.Extends(K, Type.Literal('z'), Type.Literal(3), Type.Never())))
)
})
Assert.IsEqual(M, Type.Object({
x: Type.Literal(1),
y: Type.Literal(2),
z: Type.Literal(3),
}))
})
it('Should guard mapped 13', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
z: Type.Boolean()
})
const M = Type.Mapped(Type.KeyOf(T), K => {
return (
Type.Extends(Type.Index(T, K), Type.Number(), Type.Literal(3),
Type.Extends(Type.Index(T, K), Type.String(), Type.Literal(2),
Type.Extends(Type.Index(T, K), Type.Boolean(), Type.Literal(1), Type.Never())))
)
})
Assert.IsEqual(M, Type.Object({
x: Type.Literal(3),
y: Type.Literal(2),
z: Type.Literal(1),
}))
})
// ----------------------------------------------------------------
// Exclude
// ----------------------------------------------------------------
it('Should guard mapped 14', () => {
const T = Type.Object({
x: Type.Union([Type.String(), Type.Number(), Type.Boolean()])
})
const M = Type.Mapped(Type.KeyOf(T), K => {
return Type.Exclude(Type.Index(T, K), Type.String())
})
Assert.IsEqual(M, Type.Object({
x: Type.Union([Type.Number(), Type.Boolean()])
}))
})
it('Should guard mapped 15', () => {
const T = Type.Object({
x: Type.Union([Type.String(), Type.Number(), Type.Boolean()])
})
const M = Type.Mapped(Type.KeyOf(T), K => {
return Type.Exclude(Type.Index(T, K), Type.Union([
Type.String(),
Type.Number()
]))
})
Assert.IsEqual(M, Type.Object({
x: Type.Boolean()
}))
})
it('Should guard mapped 16', () => {
const T = Type.Object({
x: Type.Union([Type.String(), Type.Number(), Type.Boolean()])
})
const M = Type.Mapped(Type.KeyOf(T), K => {
return Type.Exclude(Type.Index(T, K), Type.Null())
})
Assert.IsEqual(M, Type.Object({
x: Type.Union([Type.String(), Type.Number(), Type.Boolean()])
}))
})
// ----------------------------------------------------------------
// Non-Evaluated
// ----------------------------------------------------------------
it('Should guard mapped 17', () => {
const T = Type.Object({ x: Type.Number() })
const M = Type.Mapped(Type.KeyOf(T), K => Type.Array(Type.Index(T, K)))
Assert.IsEqual(M, Type.Object({ x: Type.Array(Type.Number()) }))
})
it('Should guard mapped 18', () => {
const T = Type.Object({ x: Type.Number() })
const M = Type.Mapped(Type.KeyOf(T), K => Type.Promise(Type.Index(T, K)))
Assert.IsEqual(M, Type.Object({ x: Type.Promise(Type.Number()) }))
})
it('Should guard mapped 19', () => {
const T = Type.Object({ x: Type.Number() })
const M = Type.Mapped(Type.KeyOf(T), K => Type.Function([Type.Index(T, K)], Type.Index(T, K)))
Assert.IsEqual(M, Type.Object({ x: Type.Function([Type.Number()], Type.Number())}))
})
it('Should guard mapped 20', () => {
const T = Type.Object({ x: Type.Number() })
const M = Type.Mapped(Type.KeyOf(T), K => Type.Tuple([Type.Index(T, K), Type.Index(T, K)]))
Assert.IsEqual(M, Type.Object({ x: Type.Tuple([Type.Number(), Type.Number()]) }))
})
it('Should guard mapped 21', () => {
const T = Type.Object({ x: Type.Number() })
const M = Type.Mapped(Type.KeyOf(T), K => Type.Union([Type.Index(T, K), Type.Index(T, K)]))
Assert.IsEqual(M, Type.Object({ x: Type.Union([Type.Number(), Type.Number()]) }))
})
it('Should guard mapped 22', () => {
const T = Type.Object({ x: Type.Number() })
const M = Type.Mapped(Type.KeyOf(T), K => Type.Intersect([Type.Index(T, K), Type.Index(T, K)]))
Assert.IsEqual(M, Type.Object({ x: Type.Intersect([Type.Number(), Type.Number()]) }))
})
// ----------------------------------------------------------------
// Numeric Keys
// ----------------------------------------------------------------
it('Should guard mapped 23', () => {
const T = Type.Object({
0: Type.Number(),
1: Type.Number(),
2: Type.Number()
})
const M = Type.Mapped(Type.KeyOf(T), K => K)
Assert.IsEqual(M, Type.Object({
0: Type.Literal('0'),
1: Type.Literal('1'),
2: Type.Literal('2'),
}))
})
it('Should guard mapped 24', () => {
const T = Type.Object({
0: Type.Number(),
1: Type.Number(),
2: Type.Number()
})
const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K))
Assert.IsEqual(M, Type.Object({
0: Type.Number(),
1: Type.Number(),
2: Type.Number(),
}))
})
it('Should guard mapped 25', () => {
const T = Type.Object({
0: Type.Number(),
1: Type.Number(),
2: Type.Number()
})
const M = Type.Mapped(Type.KeyOf(T), K => Type.String())
Assert.IsEqual(M, Type.Object({
0: Type.String(),
1: Type.String(),
2: Type.String(),
}))
})
it('Should guard mapped 26', () => {
const T = Type.Object({
0: Type.Number(),
1: Type.Number(),
2: Type.Number()
})
const M = Type.Mapped(Type.KeyOf(T), K => Type.Extends(K, Type.Literal('1'), Type.String(), Type.Number()))
Assert.IsEqual(M, Type.Object({
0: Type.Number(),
1: Type.String(),
2: Type.Number(),
}))
})
// ----------------------------------------------------------------
// Modifiers: Optional
// ----------------------------------------------------------------
it('Should guard mapped 27', () => {
const T = Type.Object({
x: Type.Optional(Type.Number()),
y: Type.Number()
})
// subtractive
const M = Type.Mapped(Type.KeyOf(T), K => Type.Optional(Type.Index(T, K), false))
Assert.IsEqual(M, Type.Object({
x: Type.Number(),
y: Type.Number()
}))
})
it('Should guard mapped 28', () => {
const T = Type.Object({
x: Type.Optional(Type.Number()),
y: Type.Number()
})
// additive
const M = Type.Mapped(Type.KeyOf(T), K => Type.Optional(Type.Index(T, K), true))
Assert.IsEqual(M, Type.Object({
x: Type.Optional(Type.Number()),
y: Type.Optional(Type.Number())
}))
})
// ----------------------------------------------------------------
// Modifiers: Readonly
// ----------------------------------------------------------------
it('Should guard mapped 27', () => {
const T = Type.Object({
x: Type.Readonly(Type.Number()),
y: Type.Number()
})
// subtractive
const M = Type.Mapped(Type.KeyOf(T), K => Type.Readonly(Type.Index(T, K), false))
Assert.IsEqual(M, Type.Object({
x: Type.Number(),
y: Type.Number()
}))
})
it('Should guard mapped 28', () => {
const T = Type.Object({
x: Type.Readonly(Type.Number()),
y: Type.Number()
})
// additive
const M = Type.Mapped(Type.KeyOf(T), K => Type.Readonly(Type.Index(T, K), true))
Assert.IsEqual(M, Type.Object({
x: Type.Readonly(Type.Number()),
y: Type.Readonly(Type.Number())
}))
})
// ----------------------------------------------------------------
// Finite Boolean
// ----------------------------------------------------------------
it('Should guard mapped 29', () => {
const T = Type.TemplateLiteral('${boolean}')
const M = Type.Mapped(T, K => K)
Assert.IsEqual(M, Type.Object({
true: Type.Literal('true'),
false: Type.Literal('false'),
}))
})
it('Should guard mapped 30', () => {
const T = Type.TemplateLiteral('${0|1}${boolean}')
const M = Type.Mapped(T, K => K)
Assert.IsEqual(M, Type.Object({
'0true': Type.Literal('0true'),
'0false': Type.Literal('0false'),
'1true': Type.Literal('1true'),
'1false': Type.Literal('1false'),
}))
})
it('Should guard mapped 31', () => {
const T = Type.TemplateLiteral('${boolean}${0|1}')
const M = Type.Mapped(T, K => K)
Assert.IsEqual(M, Type.Object({
'true0': Type.Literal('true0'),
'true1': Type.Literal('true1'),
'false0': Type.Literal('false0'),
'false1': Type.Literal('false1'),
}))
})
// ----------------------------------------------------------------
// Numeric Mapping
// ----------------------------------------------------------------
it('Should guard mapped 32', () => {
const T = Type.TemplateLiteral([
Type.Union([Type.Literal(0), Type.Literal(1)]),
Type.Union([Type.Literal(0), Type.Literal(1)]),
])
const M = Type.Mapped(T, (K) => K)
Assert.IsEqual(M, Type.Object({
'00': Type.Literal('00'),
'01': Type.Literal('01'),
'10': Type.Literal('10'),
'11': Type.Literal('11'),
}))
})
// ----------------------------------------------------------------
// Indexed Key Remap
// ----------------------------------------------------------------
it('Should guard mapped 33', () => {
const T = Type.Object({
hello: Type.Number(),
world: Type.String(),
})
const M = Type.Mapped(Type.Uppercase(Type.KeyOf(T)), (K) => {
return Type.Index(T, Type.Lowercase(K))
})
Assert.IsEqual(M, Type.Object({
HELLO: Type.Number(),
WORLD: Type.String()
}))
})
// ----------------------------------------------------------------
// Partial
// ----------------------------------------------------------------
it('Should guard mapped 34', () => {
const T = Type.Object({
x: Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
y: Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
})
const M = Type.Mapped(Type.KeyOf(T), (K) => {
return Type.Partial(Type.Index(T, K))
})
Assert.IsEqual(M, Type.Object({
x: Type.Partial(Type.Object({
x: Type.Optional(Type.Number()),
y: Type.Optional(Type.Number()),
})),
y: Type.Partial(Type.Object({
x: Type.Optional(Type.Number()),
y: Type.Optional(Type.Number()),
})),
}))
})
// ----------------------------------------------------------------
// Required
// ----------------------------------------------------------------
it('Should guard mapped 35', () => {
const T = Type.Object({
x: Type.Partial(Type.Object({
x: Type.Number(),
y: Type.Number(),
})),
y: Type.Partial(Type.Object({
x: Type.Number(),
y: Type.Number(),
})),
})
const M = Type.Mapped(Type.KeyOf(T), (K) => {
return Type.Required(Type.Index(T, K))
})
Assert.IsEqual(M, Type.Object({
x: Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
y: Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
}))
})
// ------------------------------------------------------------------
// Pick With Key
// ------------------------------------------------------------------
it('Should guard mapped 36', () => {
const T = Type.Object({
x: Type.Object({
x: Type.Number(),
y: Type.Number()
}),
y: Type.Object({
x: Type.Number(),
y: Type.Number()
})
})
const M = Type.Mapped(Type.KeyOf(T), K => {
return Type.Pick(T, K)
})
Assert.IsEqual(M, Type.Object({
x: Type.Object({
x: Type.Object({
x: Type.Number(),
y: Type.Number(),
})
}),
y: Type.Object({
y: Type.Object({
x: Type.Number(),
y: Type.Number(),
})
}),
}))
})
// ------------------------------------------------------------------
// Pick With Result
// ------------------------------------------------------------------
it('Should guard mapped 37', () => {
const T = Type.Object({
x: Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
y: Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
})
const M = Type.Mapped(Type.KeyOf(T), (K) => {
return Type.Pick(Type.Index(T, K), ['x'])
})
Assert.IsEqual(M, Type.Object({
x: Type.Object({ x: Type.Number() }),
y: Type.Object({ x: Type.Number() })
}))
})
// ------------------------------------------------------------------
// Omit With Key
// ------------------------------------------------------------------
it('Should guard mapped 36', () => {
const T = Type.Object({
x: Type.Object({
x: Type.Number(),
y: Type.Number()
}),
y: Type.Object({
x: Type.Number(),
y: Type.Number()
})
})
const M = Type.Mapped(Type.KeyOf(T), K => {
return Type.Omit(T, K)
})
Assert.IsEqual(M, Type.Object({
x: Type.Object({
y: Type.Object({
x: Type.Number(),
y: Type.Number(),
})
}),
y: Type.Object({
x: Type.Object({
x: Type.Number(),
y: Type.Number(),
})
}),
}))
})
// ------------------------------------------------------------------
// Omit With Result
// ------------------------------------------------------------------
it('Should guard mapped 37', () => {
const T = Type.Object({
x: Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
y: Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
})
const M = Type.Mapped(Type.KeyOf(T), (K) => {
return Type.Omit(Type.Index(T, K), ['x'])
})
Assert.IsEqual(M, Type.Object({
x: Type.Object({ y: Type.Number() }),
y: Type.Object({ y: Type.Number() })
}))
})
})

View File

@@ -0,0 +1,10 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TNot', () => {
it('Should guard for TNot', () => {
const R = KindGuard.IsNot(Type.Not(Type.String()))
Assert.IsTrue(R)
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TNull', () => {
it('Should guard for TNull', () => {
const R = KindGuard.IsNull(Type.Null())
Assert.IsTrue(R)
})
it('Should not guard for TNull', () => {
const R = KindGuard.IsNull(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TNumber', () => {
it('Should guard for TNumber', () => {
const R = KindGuard.IsNumber(Type.Number())
Assert.IsTrue(R)
})
it('Should not guard for TNumber', () => {
const R = KindGuard.IsNumber(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,19 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TObject', () => {
it('Should guard for TObject', () => {
const R = KindGuard.IsObject(
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
)
Assert.IsTrue(R)
})
it('Should not guard for TObject', () => {
const R = KindGuard.IsObject(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,129 @@
import { KindGuard, Type, Kind, TransformKind } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TOmit', () => {
// -------------------------------------------------------------------------
// case: https://github.com/sinclairzx81/typebox/issues/384
// -------------------------------------------------------------------------
it('Should support TUnsafe omit properties with no Kind', () => {
const T = Type.Omit(Type.Object({ x: Type.Unsafe({ x: 1 }), y: Type.Number() }), ['x'])
Assert.IsEqual(T.required, ['y'])
})
it('Should support TUnsafe omit properties with unregistered Kind', () => {
const T = Type.Omit(Type.Object({ x: Type.Unsafe({ x: 1, [Kind]: 'UnknownOmitType' }), y: Type.Number() }), ['x'])
Assert.IsEqual(T.required, ['y'])
})
// -------------------------------------------------------------------------
// Standard Tests
// -------------------------------------------------------------------------
it('Should Omit 1', () => {
const T = Type.Omit(
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
['x'],
)
Assert.IsTrue(KindGuard.IsNumber(T.properties.y))
Assert.IsEqual(T.required, ['y'])
})
it('Should Omit 2', () => {
const T = Type.Omit(
Type.Object({
x: Type.Number(),
y: Type.Optional(Type.Number()),
}),
['x'],
)
Assert.IsTrue(KindGuard.IsNumber(T.properties.y))
Assert.IsEqual(T.required, undefined)
})
it('Should Omit 3', () => {
const L = Type.Literal('x')
const T = Type.Omit(
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
L,
)
Assert.IsTrue(KindGuard.IsNumber(T.properties.y))
Assert.IsEqual(T.required, ['y'])
})
it('Should Omit 4', () => {
const L = Type.Literal('x')
const T = Type.Omit(Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]), L)
Assert.IsEqual(KindGuard.IsNumber(T.allOf[1].properties.y), true)
// @ts-ignore
Assert.IsEqual(T.allOf[1].properties.x, undefined)
})
it('Should Omit 5', () => {
const L = Type.Union([Type.Literal('x'), Type.Literal('y')])
const T = Type.Omit(
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
L,
)
// @ts-ignore
Assert.IsEqual(T.properties.x, undefined)
// @ts-ignore
Assert.IsEqual(T.properties.y, undefined)
// @ts-ignore
Assert.IsEqual(T.required, undefined)
})
it('Should Omit 6', () => {
const L = Type.Union([Type.Literal('x'), Type.Literal('y'), Type.Literal('z')])
const T = Type.Omit(
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
L,
)
// @ts-ignore
Assert.IsEqual(T.properties.x, undefined)
// @ts-ignore
Assert.IsEqual(T.properties.y, undefined)
// @ts-ignore
Assert.IsEqual(T.required, undefined)
})
it('Should Omit 7', () => {
const L = Type.TemplateLiteral([Type.Literal('a'), Type.Union([Type.Literal('b'), Type.Literal('c')])])
const T = Type.Omit(
Type.Object({
ab: Type.Number(),
ac: Type.Number(),
ad: Type.Number(),
}),
L,
)
Assert.IsTrue(KindGuard.IsNumber(T.properties.ad))
Assert.IsEqual(T.required, ['ad'])
})
// ----------------------------------------------------------------
// Discard
// ----------------------------------------------------------------
it('Should override $id', () => {
const A = Type.Object({ x: Type.Number() }, { $id: 'A' })
const T = Type.Omit(A, ['x'], { $id: 'T' })
Assert.IsEqual(T.$id!, 'T')
})
it('Should discard $id', () => {
const A = Type.Object({ x: Type.Number() }, { $id: 'A' })
const T = Type.Omit(A, ['x'])
Assert.IsFalse('$id' in T)
})
it('Should discard transform', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
})
const S = Type.Transform(T)
.Decode((value) => value)
.Encode((value) => value)
const R = Type.Omit(S, ['x'])
Assert.IsFalse(TransformKind in R)
})
})

View File

@@ -0,0 +1,99 @@
import { KindGuard, TypeRegistry, Type, Kind, TransformKind } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TPartial', () => {
it('Should produce a valid TSchema', () => {
const T = Type.Partial(Type.Object({ x: Type.Number() }))
Assert.IsTrue(KindGuard.IsSchema(T))
})
// -------------------------------------------------------------------------
// case: https://github.com/sinclairzx81/typebox/issues/364
// -------------------------------------------------------------------------
it('Should support TUnsafe partial properties with no Kind', () => {
const T = Type.Partial(Type.Object({ x: Type.Unsafe({ x: 1 }) }))
Assert.IsEqual(T.required, undefined)
})
it('Should support TUnsafe partial properties with unknown Kind', () => {
const T = Type.Partial(Type.Object({ x: Type.Unsafe({ [Kind]: 'UnknownPartialType', x: 1 }) }))
Assert.IsEqual(T.required, undefined)
})
it('Should support TUnsafe partial properties with known Kind', () => {
TypeRegistry.Set('KnownPartialType', () => true)
const T = Type.Partial(Type.Object({ x: Type.Unsafe({ [Kind]: 'KnownPartialType', x: 1 }) }))
Assert.IsEqual(T.required, undefined)
})
it('Should support applying partial to intersect', () => {
const A = Type.Object({ x: Type.Number() })
const B = Type.Object({ y: Type.Number() })
const I = Type.Intersect([A, B])
const T = Type.Partial(I)
Assert.IsEqual(T.allOf.length, 2)
Assert.IsEqual(T.allOf[0].required, undefined)
Assert.IsEqual(T.allOf[1].required, undefined)
})
it('Should support applying partial to union', () => {
const A = Type.Object({ x: Type.Number() })
const B = Type.Object({ y: Type.Number() })
const I = Type.Union([A, B])
const T = Type.Partial(I)
Assert.IsEqual(T.anyOf.length, 2)
Assert.IsEqual(T.anyOf[0].required, undefined)
Assert.IsEqual(T.anyOf[1].required, undefined)
})
// ----------------------------------------------------------------
// Discard
// ----------------------------------------------------------------
it('Should override $id', () => {
const A = Type.Object({ x: Type.Number() }, { $id: 'A' })
const T = Type.Partial(A, { $id: 'T' })
Assert.IsEqual(T.$id!, 'T')
})
it('Should discard $id', () => {
const A = Type.Object({ x: Type.Number() }, { $id: 'A' })
const T = Type.Partial(A)
Assert.IsFalse('$id' in T)
})
it('Should discard transform', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
})
const S = Type.Transform(T)
.Decode((value) => value)
.Encode((value) => value)
const R = Type.Partial(S)
Assert.IsFalse(TransformKind in R)
})
// ------------------------------------------------------------------
// Intrinsic Passthough
// https://github.com/sinclairzx81/typebox/issues/1169
// ------------------------------------------------------------------
it('Should pass through on intrinsic types on union 1', () => {
const T = Type.Partial(
Type.Union([
Type.Number(),
Type.Object({
x: Type.Number(),
}),
]),
)
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsTrue(KindGuard.IsNumber(T.anyOf[0]))
Assert.IsTrue(KindGuard.IsObject(T.anyOf[1]))
Assert.IsTrue(KindGuard.IsOptional(T.anyOf[1].properties.x))
})
it('Should pass through on intrinsic types on union 2', () => {
const T = Type.Partial(
Type.Union([
Type.Literal(1),
Type.Object({
x: Type.Number(),
}),
]),
)
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsTrue(KindGuard.IsLiteral(T.anyOf[0]))
Assert.IsTrue(KindGuard.IsObject(T.anyOf[1]))
Assert.IsTrue(KindGuard.IsOptional(T.anyOf[1].properties.x))
})
})

View File

@@ -0,0 +1,131 @@
import { KindGuard, Type, Kind, TransformKind } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TPick', () => {
// -------------------------------------------------------------------------
// case: https://github.com/sinclairzx81/typebox/issues/384
// -------------------------------------------------------------------------
it('Should support TUnsafe omit properties with no Kind', () => {
const T = Type.Pick(
Type.Object({
x: Type.Unsafe({ x: 1 }),
y: Type.Number(),
}),
['x'],
)
Assert.IsEqual(T.required, ['x'])
})
it('Should support TUnsafe omit properties with unregistered Kind', () => {
const T = Type.Pick(Type.Object({ x: Type.Unsafe({ x: 1, [Kind]: 'UnknownPickType' }), y: Type.Number() }), ['x'])
Assert.IsEqual(T.required, ['x'])
})
// -------------------------------------------------------------------------
// Standard Tests
// -------------------------------------------------------------------------
it('Should Pick 1', () => {
const T = Type.Pick(
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
['x'],
)
Assert.IsTrue(KindGuard.IsNumber(T.properties.x))
Assert.IsEqual(T.required, ['x'])
})
it('Should Pick 2', () => {
const T = Type.Pick(
Type.Object({
x: Type.Optional(Type.Number()),
y: Type.Number(),
}),
['x'],
)
Assert.IsTrue(KindGuard.IsNumber(T.properties.x))
Assert.IsEqual(T.required, undefined)
})
it('Should Pick 3', () => {
const L = Type.Literal('x')
const T = Type.Pick(
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
L,
)
Assert.IsTrue(KindGuard.IsNumber(T.properties.x))
Assert.IsEqual(T.required, ['x'])
})
it('Should Pick 4', () => {
const L = Type.Literal('x')
const T = Type.Pick(Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]), L)
Assert.IsTrue(KindGuard.IsNumber(T.allOf[0].properties.x))
// @ts-ignore
Assert.IsEqual(T.allOf[1].properties.y, undefined)
})
it('Should Pick 5', () => {
const L = Type.Union([Type.Literal('x'), Type.Literal('y')])
const T = Type.Pick(
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
L,
)
Assert.IsTrue(KindGuard.IsNumber(T.properties.x))
Assert.IsTrue(KindGuard.IsNumber(T.properties.y))
Assert.IsEqual(T.required, ['x', 'y'])
})
it('Should Pick 6', () => {
const L = Type.Union([Type.Literal('x'), Type.Literal('y'), Type.Literal('z')])
const T = Type.Pick(
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
L,
)
Assert.IsTrue(KindGuard.IsNumber(T.properties.x))
Assert.IsTrue(KindGuard.IsNumber(T.properties.y))
Assert.IsEqual(T.required, ['x', 'y'])
})
it('Should Pick 7', () => {
const L = Type.TemplateLiteral([Type.Literal('a'), Type.Union([Type.Literal('b'), Type.Literal('c')])])
const T = Type.Pick(
Type.Object({
ab: Type.Number(),
ac: Type.Number(),
ad: Type.Number(),
}),
L,
)
Assert.IsTrue(KindGuard.IsNumber(T.properties.ab))
Assert.IsTrue(KindGuard.IsNumber(T.properties.ac))
Assert.IsEqual(T.required, ['ab', 'ac'])
})
// ----------------------------------------------------------------
// Discard
// ----------------------------------------------------------------
it('Should override $id', () => {
const A = Type.Object({ x: Type.Number() }, { $id: 'A' })
const T = Type.Pick(A, ['x'], { $id: 'T' })
Assert.IsEqual(T.$id!, 'T')
})
it('Should discard $id', () => {
const A = Type.Object({ x: Type.Number() }, { $id: 'A' })
const T = Type.Pick(A, ['x'])
Assert.IsFalse('$id' in T)
})
it('Should discard transform', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
})
const S = Type.Transform(T)
.Decode((value) => value)
.Encode((value) => value)
const R = Type.Pick(S, ['x'])
Assert.IsFalse(TransformKind in R)
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TPromise', () => {
it('Should guard for TPromise', () => {
const R = KindGuard.IsPromise(Type.Promise(Type.Number()))
Assert.IsTrue(R)
})
it('Should not guard for TPromise', () => {
const R = KindGuard.IsPromise(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,176 @@
import { TypeGuard, PatternNumberExact, PatternStringExact, PatternString, PatternNeverExact } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TRecord', () => {
// -------------------------------------------------------------
// Overloads
// -------------------------------------------------------------
it('Should guard overload 1', () => {
const T = Type.Record(Type.Union([Type.Literal('A'), Type.Literal('B')]), Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsObject(T))
Assert.IsTrue(TypeGuard.IsString(T.properties.A))
Assert.IsTrue(TypeGuard.IsString(T.properties.B))
Assert.IsEqual(T.extra, 1)
})
it('Should guard overload 2', () => {
const T = Type.Record(Type.Union([Type.Literal('A')]), Type.String(), { extra: 1 }) // unwrap as literal
Assert.IsTrue(TypeGuard.IsObject(T))
Assert.IsTrue(TypeGuard.IsString(T.properties.A))
Assert.IsEqual(T.extra, 1)
})
it('Should guard overload 3', () => {
// @ts-ignore
const N = Type.Union([]) // Never
const T = Type.Record(N, Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsRecord(T))
Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNeverExact]))
Assert.IsEqual(T.extra, 1)
})
it('Should guard overload 4', () => {
// @ts-ignore
const T = Type.Record(Type.BigInt(), Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsNever(T))
})
it('Should guard overload 5', () => {
const T = Type.Record(Type.Literal('A'), Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsObject(T))
Assert.IsTrue(TypeGuard.IsString(T.properties.A))
Assert.IsEqual(T.extra, 1)
})
it('Should guard overload 6', () => {
const L = Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal('A'), Type.Literal('B')])])
const T = Type.Record(L, Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsObject(T))
Assert.IsTrue(TypeGuard.IsString(T.properties.helloA))
Assert.IsTrue(TypeGuard.IsString(T.properties.helloB))
Assert.IsEqual(T.extra, 1)
})
it('Should guard overload 7', () => {
const T = Type.Record(Type.Number(), Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsRecord(T))
Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNumberExact]))
Assert.IsEqual(T.extra, 1)
})
it('Should guard overload 8', () => {
const T = Type.Record(Type.Integer(), Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsRecord(T))
Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNumberExact]))
Assert.IsEqual(T.extra, 1)
})
it('Should guard overload 9', () => {
const T = Type.Record(Type.String(), Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsRecord(T))
Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternStringExact]))
Assert.IsEqual(T.extra, 1)
})
it('Should guard overload 10', () => {
const L = Type.TemplateLiteral([Type.String(), Type.Literal('_foo')])
const T = Type.Record(L, Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsRecord(T))
Assert.IsTrue(TypeGuard.IsString(T.patternProperties[`^${PatternString}_foo$`]))
Assert.IsEqual(T.extra, 1)
})
it('Should guard overload 11', () => {
const L = Type.Union([Type.Literal('A'), Type.Union([Type.Literal('B'), Type.Literal('C')])])
const T = Type.Record(L, Type.String())
Assert.IsTrue(TypeGuard.IsObject(T))
Assert.IsTrue(TypeGuard.IsString(T.properties.A))
Assert.IsTrue(TypeGuard.IsString(T.properties.B))
Assert.IsTrue(TypeGuard.IsString(T.properties.C))
})
it('Should guard overload 12', () => {
enum E {
A = 'X',
B = 'Y',
C = 'Z',
}
const T = Type.Enum(E)
const R = Type.Record(T, Type.Null())
Assert.IsTrue(TypeGuard.IsObject(R))
Assert.IsTrue(TypeGuard.IsNull(R.properties.X))
Assert.IsTrue(TypeGuard.IsNull(R.properties.Y))
Assert.IsTrue(TypeGuard.IsNull(R.properties.Z))
})
// ----------------------------------------------------------------
// https://github.com/sinclairzx81/typebox/issues/916
// ----------------------------------------------------------------
it('Should guard overload 13', () => {
// @ts-ignore
const T = Type.Record(Type.Never(), Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsRecord(T))
Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNeverExact]))
Assert.IsEqual(T.extra, 1)
})
it('Should guard overload 14', () => {
// @ts-ignore
const T = Type.Record(Type.Any(), Type.String(), { extra: 1 })
Assert.IsTrue(TypeGuard.IsRecord(T))
Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternStringExact]))
Assert.IsEqual(T.extra, 1)
})
// -------------------------------------------------------------
// Variants
// -------------------------------------------------------------
it('Should guard for TRecord', () => {
const R = TypeGuard.IsRecord(Type.Record(Type.String(), Type.Number()))
Assert.IsTrue(R)
})
it('Should guard for TRecord with TObject value', () => {
const R = TypeGuard.IsRecord(
Type.Record(
Type.String(),
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
),
)
Assert.IsTrue(R)
})
it('Should not guard for TRecord', () => {
const R = TypeGuard.IsRecord(null)
Assert.IsFalse(R)
})
it('Should not guard for TRecord with invalid $id', () => {
// @ts-ignore
const R = TypeGuard.IsRecord(Type.Record(Type.String(), Type.Number(), { $id: 1 }))
Assert.IsFalse(R)
})
it('Should not guard for TRecord with TObject value with invalid Property', () => {
const R = TypeGuard.IsRecord(
Type.Record(
Type.String(),
Type.Object({
x: Type.Number(),
y: {} as any,
}),
),
)
Assert.IsFalse(R)
})
it('Normalize: Should should normalize to TObject for single literal union value', () => {
const K = Type.Union([Type.Literal('ok')])
const R = TypeGuard.IsObject(Type.Record(K, Type.Number()))
Assert.IsTrue(R)
})
it('Normalize: Should should normalize to TObject for multi literal union value', () => {
const K = Type.Union([Type.Literal('A'), Type.Literal('B')])
const R = TypeGuard.IsObject(Type.Record(K, Type.Number()))
Assert.IsTrue(R)
})
// ------------------------------------------------------------------
// Evaluated: Dollar Sign Escape
// https://github.com/sinclairzx81/typebox/issues/794
// ------------------------------------------------------------------
// prettier-ignore
{
const K = Type.TemplateLiteral('$prop${A|B|C}') // issue
const T = Type.Record(K, Type.String())
Assert.IsTrue(TypeGuard.IsObject(T))
Assert.IsTrue(TypeGuard.IsString(T.properties.$propA))
Assert.IsTrue(TypeGuard.IsString(T.properties.$propB))
Assert.IsTrue(TypeGuard.IsString(T.properties.$propC))
Assert.IsEqual(T.required, ['$propA', '$propB', '$propC'])
}
})

View File

@@ -0,0 +1,16 @@
import { KindGuard, PatternNumberExact, PatternStringExact, PatternString, PatternNumber } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TRecursive', () => {
it('Should guard 1', () => {
const T = Type.Recursive((This) => Type.Object({ nodes: This }))
Assert.IsTrue(KindGuard.IsRecursive(T))
Assert.IsTrue(KindGuard.IsObject(T))
})
it('Should guard 2', () => {
const T = Type.Recursive((This) => Type.Tuple([This]))
Assert.IsTrue(KindGuard.IsRecursive(T))
Assert.IsTrue(KindGuard.IsTuple(T))
})
})

View File

@@ -0,0 +1,36 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TRef', () => {
// ----------------------------------------------------------------
// Deprecated
// ----------------------------------------------------------------
it('Should guard for Ref(Schema) 1', () => {
const T = Type.Number({ $id: 'T' })
const R = Type.Ref(T)
Assert.IsTrue(KindGuard.IsRef(R))
Assert.IsTrue(typeof R['$ref'] === 'string')
})
it('Should guard for Ref(Schema) 2', () => {
const T = Type.Number()
Assert.Throws(() => Type.Ref(T))
})
it('Should guard for Ref(Schema) 3', () => {
// @ts-ignore
const T = Type.Number({ $id: null })
Assert.Throws(() => Type.Ref(T))
})
// ----------------------------------------------------------------
// Standard
// ----------------------------------------------------------------
it('Should guard for TRef', () => {
const T = Type.Number({ $id: 'T' })
const R = KindGuard.IsRef(Type.Ref(T))
Assert.IsTrue(R)
})
it('Should not guard for TRef', () => {
const R = KindGuard.IsRef(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,18 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TRegExp', () => {
it('Should guard for TRegExp 1', () => {
const T = Type.RegExp(/foo/, { $id: 'T' })
Assert.IsTrue(KindGuard.IsSchema(T))
})
it('Should guard for TRegExp 1', () => {
const T = Type.RegExp(/foo/, { $id: 'T' })
Assert.IsTrue(KindGuard.IsRegExp(T))
})
it('Should guard for TRegExp 2', () => {
const T = Type.RegExp('foo', { $id: 'T' })
Assert.IsTrue(KindGuard.IsRegExp(T))
})
})

View File

@@ -0,0 +1,96 @@
import { KindGuard, TypeRegistry, Type, Kind, TransformKind } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TRequired', () => {
it('Should produce a valid TSchema', () => {
const T = Type.Required(Type.Object({ x: Type.Number() }))
Assert.IsTrue(KindGuard.IsSchema(T))
})
it('Should support TUnsafe required properties with no Kind', () => {
const T = Type.Required(Type.Object({ x: Type.Optional(Type.Unsafe({ x: 1 })) }))
Assert.IsEqual(T.required, ['x'])
})
it('Should support TUnsafe required properties with unknown Kind', () => {
const T = Type.Required(Type.Object({ x: Type.Optional(Type.Unsafe({ [Kind]: 'UnknownRequiredType', x: 1 })) }))
Assert.IsEqual(T.required, ['x'])
})
it('Should support TUnsafe required properties with known Kind', () => {
TypeRegistry.Set('KnownRequiredType', () => true)
const T = Type.Required(Type.Object({ x: Type.Optional(Type.Unsafe({ [Kind]: 'KnownRequiredType', x: 1 })) }))
Assert.IsEqual(T.required, ['x'])
})
it('Should support applying required to intersect', () => {
const A = Type.Object({ x: Type.Optional(Type.Number()) })
const B = Type.Object({ y: Type.Optional(Type.Number()) })
const I = Type.Intersect([A, B])
const T = Type.Required(I)
Assert.IsEqual(T.allOf.length, 2)
Assert.IsEqual(T.allOf[0].required, ['x'])
Assert.IsEqual(T.allOf[1].required, ['y'])
})
it('Should support applying required to union', () => {
const A = Type.Object({ x: Type.Optional(Type.Number()) })
const B = Type.Object({ y: Type.Optional(Type.Number()) })
const I = Type.Union([A, B])
const T = Type.Required(I)
Assert.IsEqual(T.anyOf.length, 2)
Assert.IsEqual(T.anyOf[0].required, ['x'])
Assert.IsEqual(T.anyOf[1].required, ['y'])
})
// ----------------------------------------------------------------
// Discard
// ----------------------------------------------------------------
it('Should override $id', () => {
const A = Type.Object({ x: Type.Number() }, { $id: 'A' })
const T = Type.Required(A, { $id: 'T' })
Assert.IsEqual(T.$id!, 'T')
})
it('Should discard $id', () => {
const A = Type.Object({ x: Type.Number() }, { $id: 'A' })
const T = Type.Required(A)
Assert.IsFalse('$id' in T)
})
it('Should discard transform', () => {
const T = Type.Object({
x: Type.Number(),
y: Type.String(),
})
const S = Type.Transform(T)
.Decode((value) => value)
.Encode((value) => value)
const R = Type.Required(S)
Assert.IsFalse(TransformKind in R)
})
// ------------------------------------------------------------------
// Intrinsic Passthough
// https://github.com/sinclairzx81/typebox/issues/1169
// ------------------------------------------------------------------
it('Should pass through on intrinsic types on union 1', () => {
const T = Type.Required(
Type.Union([
Type.Number(),
Type.Object({
x: Type.Optional(Type.Number()),
}),
]),
)
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsTrue(KindGuard.IsNumber(T.anyOf[0]))
Assert.IsTrue(KindGuard.IsObject(T.anyOf[1]))
Assert.IsFalse(KindGuard.IsOptional(T.anyOf[1].properties.x))
})
it('Should pass through on intrinsic types on union 2', () => {
const T = Type.Required(
Type.Union([
Type.Literal(1),
Type.Object({
x: Type.Optional(Type.Number()),
}),
]),
)
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsTrue(KindGuard.IsLiteral(T.anyOf[0]))
Assert.IsTrue(KindGuard.IsObject(T.anyOf[1]))
Assert.IsFalse(KindGuard.IsOptional(T.anyOf[1].properties.x))
})
})

View File

@@ -0,0 +1,59 @@
import { Type, KindGuard } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TRest', () => {
it('Should guard 1', () => {
// union never
const A = Type.String()
const B = Type.Union(Type.Rest(A))
Assert.IsTrue(KindGuard.IsNever(B))
})
it('Should guard 2', () => {
// intersect never
const A = Type.String()
const B = Type.Intersect(Type.Rest(A))
Assert.IsTrue(KindGuard.IsNever(B))
})
it('Should guard 3', () => {
// tuple
const A = Type.Tuple([Type.Number(), Type.String()])
const B = Type.Union(Type.Rest(A))
Assert.IsTrue(KindGuard.IsUnion(B))
Assert.IsEqual(B.anyOf.length, 2)
Assert.IsTrue(KindGuard.IsNumber(B.anyOf[0]))
Assert.IsTrue(KindGuard.IsString(B.anyOf[1]))
})
it('Should guard 4', () => {
// tuple spread
const A = Type.Tuple([Type.Literal(1), Type.Literal(2)])
const B = Type.Tuple([Type.Literal(3), Type.Literal(4)])
const C = Type.Tuple([...Type.Rest(A), ...Type.Rest(B)])
Assert.IsTrue(KindGuard.IsTuple(C))
Assert.IsEqual(C.items!.length, 4)
Assert.IsEqual(C.items![0].const, 1)
Assert.IsEqual(C.items![1].const, 2)
Assert.IsEqual(C.items![2].const, 3)
Assert.IsEqual(C.items![3].const, 4)
})
it('Should guard 5', () => {
// union to intersect
const A = Type.Object({ x: Type.Number() })
const B = Type.Object({ y: Type.String() })
const C = Type.Union([A, B])
const D = Type.Intersect(Type.Rest(C))
Assert.IsTrue(KindGuard.IsIntersect(D))
Assert.IsEqual(D.allOf.length, 2)
Assert.IsTrue(KindGuard.IsObject(D.allOf[0]))
Assert.IsTrue(KindGuard.IsObject(D.allOf[1]))
})
it('Should guard 6', () => {
// intersect to composite
const A = Type.Object({ x: Type.Number() })
const B = Type.Object({ y: Type.String() })
const C = Type.Intersect([A, B])
const D = Type.Composite(Type.Rest(C))
Assert.IsTrue(KindGuard.IsObject(D))
Assert.IsTrue(KindGuard.IsNumber(D.properties.x))
Assert.IsTrue(KindGuard.IsString(D.properties.y))
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TString', () => {
it('Should guard for TString', () => {
const R = KindGuard.IsString(Type.String())
Assert.IsTrue(R)
})
it('Should not guard for TString', () => {
const R = KindGuard.IsString(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TSymbol', () => {
it('Should guard for TSymbol', () => {
const R = KindGuard.IsSymbol(Type.Symbol())
Assert.IsTrue(R)
})
it('Should not guard for TSymbol', () => {
const R = KindGuard.IsSymbol(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,35 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TTemplateLiteral', () => {
it('Should guard for empty TemplateLiteral', () => {
const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([]))
Assert.IsTrue(R)
})
it('Should guard for TSchema', () => {
const R = KindGuard.IsSchema(Type.TemplateLiteral([]))
Assert.IsTrue(R)
})
it('Should guard for TemplateLiteral (TTemplateLiteral)', () => {
const T = Type.TemplateLiteral([Type.Literal('hello')])
const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([T, Type.Literal('world')]))
Assert.IsTrue(R)
})
it('Should guard for TemplateLiteral (TLiteral)', () => {
const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.Literal('hello')]))
Assert.IsTrue(R)
})
it('Should guard for TemplateLiteral (TString)', () => {
const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.String()]))
Assert.IsTrue(R)
})
it('Should guard for TemplateLiteral (TNumber)', () => {
const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.Number()]))
Assert.IsTrue(R)
})
it('Should guard for TemplateLiteral (TBoolean)', () => {
const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.Boolean()]))
Assert.IsTrue(R)
})
})

View File

@@ -0,0 +1,13 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TThis', () => {
it('Should guard for TThis', () => {
Type.Recursive((This) => {
const R = KindGuard.IsThis(This)
Assert.IsTrue(R)
return Type.Object({ nodes: Type.Array(This) })
})
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TTuple', () => {
it('Should guard for TTuple', () => {
const R = KindGuard.IsTuple(Type.Tuple([Type.Number(), Type.Number()]))
Assert.IsTrue(R)
})
it('Should not guard for TTuple', () => {
const R = KindGuard.IsTuple(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TUint8Array', () => {
it('Should guard for TUint8Array', () => {
const R = KindGuard.IsUint8Array(Type.Uint8Array())
Assert.IsTrue(R)
})
it('Should not guard for TUint8Array', () => {
const R = KindGuard.IsUint8Array(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,33 @@
import { KindGuard, Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/Uncapitalize', () => {
it('Should guard for Uncapitalize 1', () => {
const T = Type.Uncapitalize(Type.Literal('HELLO'), { $id: 'hello', foo: 1 })
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'hELLO')
Assert.IsEqual(T.$id, 'hello')
Assert.IsEqual(T.foo, 1)
})
it('Should guard for Uncapitalize 2', () => {
const T = Type.Uncapitalize(Type.Literal('HELLO'))
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'hELLO')
})
it('Should guard for Uncapitalize 3', () => {
const T = Type.Uncapitalize(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD')]))
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 'hELLO')
Assert.IsEqual(T.anyOf[1].const, 'wORLD')
})
it('Should guard for Uncapitalize 4', () => {
const T = Type.Uncapitalize(Type.TemplateLiteral('HELLO${0|1}'))
Assert.IsTrue(KindGuard.IsTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(hELLO0|hELLO1)$')
})
it('Should guard for Uncapitalize 5', () => {
const T = Type.Uncapitalize(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(0), Type.Literal(1)])]))
Assert.IsTrue(KindGuard.IsTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(hELLO0|hELLO1)$')
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TUndefined', () => {
it('Should guard for TUndefined', () => {
const R = KindGuard.IsUndefined(Type.Undefined())
Assert.IsTrue(R)
})
it('Should not guard for TUndefined', () => {
const R = KindGuard.IsUndefined(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,42 @@
import { TSchema, KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TUnion', () => {
it('Should guard for TUnion', () => {
const R = KindGuard.IsUnion(
Type.Union([
Type.Object({
x: Type.Number(),
}),
Type.Object({
y: Type.Number(),
}),
]),
)
Assert.IsTrue(R)
})
it('Should not guard for TUnion', () => {
const R = KindGuard.IsUnion(null)
Assert.IsFalse(R)
})
it('Transform: Should transform to never for zero length union', () => {
const T = Type.Union([])
const R = KindGuard.IsNever(T)
Assert.IsTrue(R)
})
it('Transform: Should unwrap union type for array of length === 1', () => {
const T = Type.Union([Type.String()])
const R = KindGuard.IsString(T)
Assert.IsTrue(R)
})
it('Transform: Should retain union if array length > 1', () => {
const T = Type.Union([Type.String(), Type.Number()])
const R1 = KindGuard.IsUnion(T)
const R2 = KindGuard.IsString(T.anyOf[0])
const R3 = KindGuard.IsNumber(T.anyOf[1])
Assert.IsTrue(R1)
Assert.IsTrue(R2)
Assert.IsTrue(R3)
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TUnknown', () => {
it('Should guard for TUnknown', () => {
const R = KindGuard.IsUnknown(Type.Unknown())
Assert.IsTrue(R)
})
it('Should not guard for TUnknown', () => {
const R = KindGuard.IsUnknown(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,33 @@
import { Kind, KindGuard, TypeRegistry } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TUnsafe', () => {
it('Should guard raw TUnsafe', () => {
const T = Type.Unsafe({ x: 1 })
const R = KindGuard.IsUnsafe(T)
Assert.IsTrue(R)
})
it('Should guard raw TUnsafe as TSchema', () => {
const T = Type.Unsafe({ x: 1 })
const R = KindGuard.IsSchema(T)
Assert.IsTrue(R)
})
it('Should guard override TUnsafe as TSchema when registered', () => {
TypeRegistry.Set('UnsafeType', () => true)
const T = Type.Unsafe({ [Kind]: 'UnsafeType' })
const R = KindGuard.IsSchema(T)
Assert.IsTrue(R)
TypeRegistry.Delete('UnsafeType')
})
it('Should not guard TUnsafe with unregistered kind', () => {
const T = Type.Unsafe({ [Kind]: 'UnsafeType' })
const R = KindGuard.IsUnsafe(T)
Assert.IsFalse(R)
})
it('Should not guard for TString', () => {
const T = Type.String()
const R = KindGuard.IsUnsafe(T)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,33 @@
import { KindGuard, Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/Uppercase', () => {
it('Should guard for Uppercase 1', () => {
const T = Type.Uppercase(Type.Literal('hello'), { $id: 'hello', foo: 1 })
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'HELLO')
Assert.IsEqual(T.$id, 'hello')
Assert.IsEqual(T.foo, 1)
})
it('Should guard for Uppercase 2', () => {
const T = Type.Uppercase(Type.Literal('hello'))
Assert.IsTrue(KindGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'HELLO')
})
it('Should guard for Uppercase 3', () => {
const T = Type.Uppercase(Type.Union([Type.Literal('hello'), Type.Literal('world')]))
Assert.IsTrue(KindGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 'HELLO')
Assert.IsEqual(T.anyOf[1].const, 'WORLD')
})
it('Should guard for Uppercase 4', () => {
const T = Type.Uppercase(Type.TemplateLiteral('hello${0|1}'))
Assert.IsTrue(KindGuard.IsTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(HELLO0|HELLO1)$')
})
it('Should guard for Uppercase 5', () => {
const T = Type.Uppercase(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(0), Type.Literal(1)])]))
Assert.IsTrue(KindGuard.IsTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(HELLO0|HELLO1)$')
})
})

View File

@@ -0,0 +1,14 @@
import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/kind/TVoid', () => {
it('Should guard for TVoid', () => {
const R = KindGuard.IsVoid(Type.Void())
Assert.IsTrue(R)
})
it('Should not guard for TVoid', () => {
const R = KindGuard.IsVoid(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,19 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TAny', () => {
it('Should guard for TAny', () => {
const R = TypeGuard.IsAny(Type.Any())
Assert.IsTrue(R)
})
it('Should not guard for TAny', () => {
const R = TypeGuard.IsAny(null)
Assert.IsFalse(R)
})
it('Should not guard for TAny with invalid $id', () => {
// @ts-ignore
const R = TypeGuard.IsAny(Type.Any({ $id: 1 }))
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,14 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TArgument', () => {
it('Should guard for TArgument', () => {
const R = TypeGuard.IsArgument(Type.Argument(0))
Assert.IsTrue(R)
})
it('Should not guard for TArgument', () => {
const R = TypeGuard.IsArgument(null)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,56 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TArray', () => {
it('Should guard for TArray', () => {
const R = TypeGuard.IsArray(Type.Array(Type.Number()))
Assert.IsTrue(R)
})
it('Should not guard for TArray', () => {
const R = TypeGuard.IsArray(null)
Assert.IsFalse(R)
})
it('Should guard for nested object TArray', () => {
const R = TypeGuard.IsArray(
Type.Array(
Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
),
)
Assert.IsTrue(R)
})
it('Should not guard for nested object TArray', () => {
const R = TypeGuard.IsArray(
Type.Array(
Type.Object({
x: Type.Number(),
y: {} as any,
}),
),
)
Assert.IsFalse(R)
})
it('Should not guard for TArray with invalid $id', () => {
// @ts-ignore
const R = TypeGuard.IsArray(Type.Array(Type.Number(), { $id: 1 }))
Assert.IsFalse(R)
})
it('Should not guard for TArray with invalid minItems', () => {
// @ts-ignore
const R = TypeGuard.IsArray(Type.Array(Type.String(), { minItems: '1' }))
Assert.IsFalse(R)
})
it('Should not guard for TArray with invalid maxItems', () => {
// @ts-ignore
const R = TypeGuard.IsArray(Type.Array(Type.String(), { maxItems: '1' }))
Assert.IsFalse(R)
})
it('Should not guard for TArray with invalid uniqueItems', () => {
// @ts-ignore
const R = TypeGuard.IsArray(Type.Array(Type.String(), { uniqueItems: '1' }))
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,22 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TAsyncIterator', () => {
it('Should guard for TAsyncIterator', () => {
const T = Type.AsyncIterator(Type.Any())
const R = TypeGuard.IsAsyncIterator(T)
Assert.IsTrue(R)
})
it('Should not guard for TAsyncIterator', () => {
const T = null
const R = TypeGuard.IsAsyncIterator(T)
Assert.IsFalse(R)
})
it('Should not guard for TAsyncIterator with invalid $id', () => {
//@ts-ignore
const T = Type.AsyncIterator(Type.Any(), { $id: 1 })
const R = TypeGuard.IsAsyncIterator(T)
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,41 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/Awaited', () => {
it('Should guard for Awaited 1', () => {
const T = Type.Awaited(Type.String())
const R = TypeGuard.IsString(T)
Assert.IsTrue(R)
})
it('Should guard for Awaited 2', () => {
const T = Type.Awaited(Type.Promise(Type.String()))
const R = TypeGuard.IsString(T)
Assert.IsTrue(R)
})
it('Should guard for Awaited 3', () => {
const T = Type.Awaited(Type.Awaited(Type.Promise(Type.String())))
const R = TypeGuard.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(TypeGuard.IsString(T))
})
it('Should guard for Awaited 5', () => {
const T = Type.Awaited(Type.Union([Type.Promise(Type.Promise(Type.String())), Type.Number()]))
Assert.IsTrue(TypeGuard.IsUnion(T))
Assert.IsTrue(TypeGuard.IsString(T.anyOf[0]))
Assert.IsTrue(TypeGuard.IsNumber(T.anyOf[1]))
})
it('Should guard for Awaited 6', () => {
const T = Type.Awaited(Type.Intersect([Type.Promise(Type.Promise(Type.String()))]))
Assert.IsTrue(TypeGuard.IsString(T))
})
it('Should guard for Awaited 7', () => {
const T = Type.Awaited(Type.Intersect([Type.Promise(Type.Promise(Type.String())), Type.Number()]))
Assert.IsTrue(TypeGuard.IsIntersect(T))
Assert.IsTrue(TypeGuard.IsString(T.allOf[0]))
Assert.IsTrue(TypeGuard.IsNumber(T.allOf[1]))
})
})

View File

@@ -0,0 +1,19 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TBigInt', () => {
it('Should guard for TBigInt', () => {
const R = TypeGuard.IsBigInt(Type.BigInt())
Assert.IsTrue(R)
})
it('Should not guard for TBigInt', () => {
const R = TypeGuard.IsBigInt(null)
Assert.IsFalse(R)
})
it('Should not guard for BigInt with invalid $id', () => {
// @ts-ignore
const R = TypeGuard.IsBigInt(Type.BigInt({ $id: 1 }))
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,19 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TBoolean', () => {
it('Should guard for TBoolean', () => {
const R = TypeGuard.IsBoolean(Type.Boolean())
Assert.IsTrue(R)
})
it('Should not guard for TBoolean', () => {
const R = TypeGuard.IsBoolean(null)
Assert.IsFalse(R)
})
it('Should not guard for TBoolean with invalid $id', () => {
// @ts-ignore
const R = TypeGuard.IsBoolean(Type.Boolean({ $id: 1 }))
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,33 @@
import { TypeGuard, Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/Capitalize', () => {
it('Should guard for Capitalize 1', () => {
const T = Type.Capitalize(Type.Literal('hello'), { $id: 'hello', foo: 1 })
Assert.IsTrue(TypeGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'Hello')
Assert.IsEqual(T.$id, 'hello')
Assert.IsEqual(T.foo, 1)
})
it('Should guard for Capitalize 2', () => {
const T = Type.Capitalize(Type.Literal('hello'))
Assert.IsTrue(TypeGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'Hello')
})
it('Should guard for Capitalize 3', () => {
const T = Type.Capitalize(Type.Union([Type.Literal('hello'), Type.Literal('world')]))
Assert.IsTrue(TypeGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 'Hello')
Assert.IsEqual(T.anyOf[1].const, 'World')
})
it('Should guard for Capitalize 4', () => {
const T = Type.Capitalize(Type.TemplateLiteral('hello${0|1}'))
Assert.IsTrue(TypeGuard.IsTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(Hello0|Hello1)$')
})
it('Should guard for Capitalize 5', () => {
const T = Type.Capitalize(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(0), Type.Literal(1)])]))
Assert.IsTrue(TypeGuard.IsTemplateLiteral(T))
Assert.IsEqual(T.pattern, '^(Hello0|Hello1)$')
})
})

View File

@@ -0,0 +1,165 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TComposite', () => {
it('Should guard for distinct properties', () => {
const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })])
Assert.IsTrue(TypeGuard.IsNumber(T.properties.x))
Assert.IsTrue(TypeGuard.IsNumber(T.properties.y))
})
it('Should guard for overlapping properties', () => {
const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() })])
Assert.IsTrue(TypeGuard.IsIntersect(T.properties.x))
// @ts-ignore
Assert.IsTrue(TypeGuard.IsNumber(T.properties.x.allOf[0]))
// @ts-ignore
Assert.IsTrue(TypeGuard.IsNumber(T.properties.x.allOf[1]))
})
it('Should not produce optional property if all properties are not optional', () => {
const T = Type.Composite([Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Number() })])
Assert.IsFalse(TypeGuard.IsOptional(T.properties.x))
})
// Note for: https://github.com/sinclairzx81/typebox/issues/419
// Determining if a composite property is optional requires a deep check for all properties gathered during a indexed access
// call. Currently, there isn't a trivial way to perform this check without running into possibly infinite instantiation issues.
// The optional check is only specific to overlapping properties. Singular properties will continue to work as expected. The
// rule is "if all composite properties for a key are optional, then the composite property is optional". Defer this test and
// document as minor breaking change.
//
it('Should produce optional property if all composited properties are optional', () => {
// prettier-ignore
const T = Type.Composite([
Type.Object({ x: Type.Optional(Type.Number()) }),
Type.Object({ x: Type.Optional(Type.Number()) })
])
Assert.IsTrue(TypeGuard.IsOptional(T.properties.x))
Assert.IsEqual(T.required, undefined)
})
// prettier-ignore
it('Should produce required property if some composited properties are not optional', () => {
const T = Type.Composite([
Type.Object({ x: Type.Optional(Type.Number()) }),
Type.Object({ x: Type.Number() })
])
Assert.IsFalse(TypeGuard.IsOptional(T.properties.x))
Assert.IsTrue(T.required!.includes('x'))
})
// prettier-ignore
it('Should preserve single optional property', () => {
const T = Type.Composite([
Type.Object({ x: Type.Optional(Type.Number()) }),
])
Assert.IsTrue(TypeGuard.IsOptional(T.properties.x))
Assert.IsEqual(T.required, undefined)
})
// ----------------------------------------------------------------
// Intersect
// ----------------------------------------------------------------
// prettier-ignore
it('Should composite Intersect 1', () => {
const T = Type.Composite([
Type.Intersect([
Type.Object({ x: Type.Number() }),
Type.Object({ y: Type.Number() }),
]),
Type.Intersect([
Type.Object({ z: Type.Number() }),
])
])
Assert.IsEqual(T, Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number()
}))
})
// prettier-ignore
it('Should composite Intersect 2', () => {
const T = Type.Composite([
Type.Intersect([
Type.Object({ x: Type.Number() }),
Type.Object({ x: Type.Number() }),
]),
Type.Intersect([
Type.Object({ x: Type.Number() }),
])
])
Assert.IsEqual(T, Type.Object({
x: Type.Intersect([Type.Intersect([Type.Number(), Type.Number()]), Type.Number()])
}))
})
// prettier-ignore
it('Should composite Intersect 3', () => {
const T = Type.Composite([
Type.Number(),
Type.Boolean()
])
Assert.IsEqual(T, Type.Object({}))
})
// prettier-ignore
it('Should composite Intersect 4', () => {
const T = Type.Composite([
Type.Number(),
Type.Boolean(),
Type.Object({ x: Type.String() })
])
Assert.IsEqual(T, Type.Object({
x: Type.String()
}))
})
// prettier-ignore
it('Should composite Intersect 5', () => {
const T = Type.Composite([
Type.Object({ x: Type.Optional(Type.String()) }),
Type.Object({ x: Type.String() })
])
Assert.IsEqual(T, Type.Object({
x: Type.Intersect([Type.String(), Type.String()])
}))
})
// prettier-ignore
it('Should composite Intersect 6', () => {
const T = Type.Composite([
Type.Object({ x: Type.Optional(Type.String()) }),
Type.Object({ x: Type.Optional(Type.String()) })
])
Assert.IsEqual(T, Type.Object({
x: Type.Optional(Type.Intersect([Type.String(), Type.String()]))
}))
})
// ----------------------------------------------------------------
// Union
// ----------------------------------------------------------------
// https://github.com/sinclairzx81/typebox/issues/789
// prettier-ignore
it('Should composite Union 1 (non-overlapping)', () => {
const T = Type.Composite([
Type.Union([
Type.Object({ x: Type.Number() }),
Type.Object({ y: Type.Number() }),
]),
Type.Union([
Type.Object({ z: Type.Number() }),
])
])
Assert.IsEqual(T, Type.Object({
z: Type.Number()
}))
})
// https://github.com/sinclairzx81/typebox/issues/789
// prettier-ignore
it('Should composite Union 2 (overlapping)', () => {
const T = Type.Composite([
Type.Union([
Type.Object({ x: Type.Number() }),
Type.Object({ x: Type.Number() }),
]),
Type.Union([
Type.Object({ x: Type.Number() }),
])
])
Assert.IsEqual(T, Type.Object({
x: Type.Intersect([Type.Union([Type.Number(), Type.Number()]), Type.Number()])
}))
})
})

View File

@@ -0,0 +1,33 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TComputed', () => {
// ----------------------------------------------------------------
// Schema
// ----------------------------------------------------------------
it('Should guard for Schema', () => {
const T = Type.Partial(Type.Ref('A'))
Assert.IsTrue(TypeGuard.IsComputed(T))
Assert.IsTrue(TypeGuard.IsSchema(T))
})
// ----------------------------------------------------------------
// Record
// ----------------------------------------------------------------
it('Should guard for Record 1', () => {
const T = Type.Record(Type.String(), Type.String())
Assert.IsTrue(TypeGuard.IsRecord(T))
})
it('Should guard for Record 3', () => {
const T = Type.Record(Type.String(), Type.Ref('A'))
Assert.IsTrue(TypeGuard.IsRecord(T))
})
it('Should guard for Record 3', () => {
const T = Type.Record(Type.String(), Type.Partial(Type.Ref('A')))
Assert.IsTrue(TypeGuard.IsRecord(T))
})
it('Should guard for Record 4', () => {
const T = Type.Record(Type.Ref('A'), Type.String())
Assert.IsTrue(TypeGuard.IsNever(T))
})
})

View File

@@ -0,0 +1,124 @@
import { TypeGuard, ValueGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TConstT', () => {
// ----------------------------------------------------------------
// Identity Types
// ----------------------------------------------------------------
it('Should guard for TConst 1', () => {
const T = Type.Const(undefined)
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsUndefined(T))
})
it('Should guard for TConst 2', () => {
const T = Type.Const(null)
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsNull(T))
})
it('Should guard for TConst 3', () => {
const T = Type.Const(Symbol())
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsSymbol(T))
})
it('Should guard for TConst 4', () => {
const T = Type.Const(1 as const)
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsLiteral(T))
Assert.IsEqual(T.const, 1)
})
it('Should guard for TConst 5', () => {
const T = Type.Const('hello' as const)
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'hello')
})
it('Should guard for TConst 6', () => {
const T = Type.Const(true as const)
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsLiteral(T))
Assert.IsEqual(T.const, true)
})
// ----------------------------------------------------------------
// Complex Types
// ----------------------------------------------------------------
it('Should guard for TConst 7', () => {
const T = Type.Const(100n as const)
Assert.IsFalse(TypeGuard.IsReadonly(T))
// TS disparity because TLiteral does not support Bigint
Assert.IsTrue(TypeGuard.IsBigInt(T))
})
it('Should guard for TConst 8', () => {
const T = Type.Const(new Date())
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsDate(T))
})
it('Should guard for TConst 9', () => {
const T = Type.Const(new Uint8Array())
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsUint8Array(T))
})
it('Should guard for TConst 10', () => {
const T = Type.Const(function () {})
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsFunction(T))
Assert.IsTrue(T.parameters.length === 0)
Assert.IsTrue(TypeGuard.IsUnknown(T.returns))
})
it('Should guard for TConst 11', () => {
const T = Type.Const(new (class {})())
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsObject(T))
// Object types that are neither Date or Uint8Array evaluate as empty objects
Assert.IsEqual(T.properties, {})
})
it('Should guard for TConst 12', () => {
const T = Type.Const((function* (): any {})())
const R = ValueGuard.IsIterator((function* (): any {})())
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsAny(T))
})
it('Should guard for TConst 13', () => {
const T = Type.Const((async function* (): any {})())
const R = ValueGuard.IsAsyncIterator((function* (): any {})())
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsAny(T))
})
it('Should guard for TConst 14', () => {
const T = Type.Const({
x: 1,
y: {
z: 2,
},
} as const)
// root
Assert.IsFalse(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsObject(T))
// x
Assert.IsTrue(TypeGuard.IsLiteral(T.properties.x))
Assert.IsEqual(T.properties.x.const, 1)
// y
Assert.IsTrue(TypeGuard.IsReadonly(T.properties.y))
Assert.IsTrue(TypeGuard.IsObject(T.properties.y))
// y.z
Assert.IsTrue(TypeGuard.IsReadonly(T.properties.y.properties.z))
Assert.IsTrue(TypeGuard.IsLiteral(T.properties.y.properties.z))
Assert.IsEqual(T.properties.y.properties.z.const, 2)
})
it('Should guard for TConst 15', () => {
const T = Type.Const([1, 2, 3] as const)
// root (arrays are always readonly as root)
Assert.IsTrue(TypeGuard.IsReadonly(T))
Assert.IsTrue(TypeGuard.IsTuple(T))
Assert.IsTrue(T.items?.length === 3)
// 0
Assert.IsFalse(TypeGuard.IsReadonly(T.items![0]))
Assert.IsTrue(TypeGuard.IsLiteral(T.items![0]))
// 1
Assert.IsFalse(TypeGuard.IsReadonly(T.items![1]))
Assert.IsTrue(TypeGuard.IsLiteral(T.items![1]))
// 2
Assert.IsFalse(TypeGuard.IsReadonly(T.items![2]))
Assert.IsTrue(TypeGuard.IsLiteral(T.items![2]))
})
})

View File

@@ -0,0 +1,35 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TConstructor', () => {
it('Should guard for TConstructor', () => {
const R = TypeGuard.IsConstructor(Type.Constructor([], Type.Number()))
Assert.IsTrue(R)
})
it('Should not guard for TConstructor', () => {
const R = TypeGuard.IsConstructor(null)
Assert.IsFalse(R)
})
it('Should not guard for TConstructor with invalid $id', () => {
// @ts-ignore
const R = TypeGuard.IsConstructor(Type.Constructor([], Type.Number(), { $id: 1 }))
Assert.IsFalse(R)
})
it('Should not guard for TConstructor with invalid Params', () => {
const R = TypeGuard.IsConstructor(Type.Constructor([{} as any, {} as any], Type.Number()))
Assert.IsFalse(R)
})
it('Should not guard for TConstructor with invalid Return', () => {
const R = TypeGuard.IsConstructor(Type.Constructor([], {} as any))
Assert.IsFalse(R)
})
it('Should guard for TConstructor with empty Rest Tuple', () => {
const R = TypeGuard.IsConstructor(Type.Constructor(Type.Rest(Type.Tuple([])), Type.Number()))
Assert.IsTrue(R)
})
it('Should guard for TConstructor with Rest Tuple', () => {
const R = TypeGuard.IsConstructor(Type.Constructor(Type.Rest(Type.Tuple([Type.Number(), Type.String()])), Type.Number()))
Assert.IsTrue(R)
})
})

View File

@@ -0,0 +1,44 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TDate', () => {
it('Should guard for TDate', () => {
const R = TypeGuard.IsDate(Type.Date())
Assert.IsTrue(R)
})
it('Should not guard for TDate', () => {
const R = TypeGuard.IsDate(null)
Assert.IsFalse(R)
})
it('Should not guard for TDate with invalid $id', () => {
// @ts-ignore
const R = TypeGuard.IsDate(Type.Date({ $id: 1 }))
Assert.IsFalse(R)
})
it('Should not guard for TDate with invalid exclusiveMaximumTimestamp', () => {
// @ts-ignore
const R = TypeGuard.IsDate(Type.Date({ exclusiveMaximumTimestamp: '1' }))
Assert.IsFalse(R)
})
it('Should not guard for TDate with invalid exclusiveMinimumTimestamp', () => {
// @ts-ignore
const R = TypeGuard.IsDate(Type.Date({ exclusiveMinimumTimestamp: '1' }))
Assert.IsFalse(R)
})
it('Should not guard for TDate with invalid maximumTimestamp', () => {
// @ts-ignore
const R = TypeGuard.IsDate(Type.Date({ maximumTimestamp: '1' }))
Assert.IsFalse(R)
})
it('Should not guard for TDate with invalid minimumTimestamp', () => {
// @ts-ignore
const R = TypeGuard.IsDate(Type.Date({ minimumTimestamp: '1' }))
Assert.IsFalse(R)
})
it('Should not guard for TDate with invalid multipleOfTimestamp', () => {
// @ts-ignore
const R = TypeGuard.IsDate(Type.Date({ multipleOfTimestamp: '1' }))
Assert.IsFalse(R)
})
})

View File

@@ -0,0 +1,143 @@
import { TypeGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'
describe('guard/type/TEnum', () => {
// ----------------------------------------------------------------
// Options
// ----------------------------------------------------------------
it('Should guard for Options 1', () => {
const T = Type.Enum({ x: 1 }, { extra: 'hello', $id: 'T' })
Assert.IsEqual(T.extra, 'hello')
Assert.IsEqual(T.$id, 'T')
})
it('Should guard for Options 2', () => {
enum E {
x,
}
const T = Type.Enum(E, { extra: 'hello', $id: 'T' })
Assert.IsEqual(T.extra, 'hello')
Assert.IsEqual(T.$id, 'T')
})
it('Should guard for Options 3', () => {
enum E {}
const T = Type.Enum(E, { extra: 'hello', $id: 'T' })
Assert.IsEqual(T.extra, 'hello')
Assert.IsEqual(T.$id, 'T')
})
it('Should guard for Options 4', () => {
const T = Type.Enum({}, { extra: 'hello', $id: 'T' })
Assert.IsEqual(T.extra, 'hello')
Assert.IsEqual(T.$id, 'T')
})
// ----------------------------------------------------------------
// Empty
// ----------------------------------------------------------------
it('Should guard for Empty 1', () => {
const T = Type.Enum({})
Assert.IsTrue(TypeGuard.IsNever(T))
})
it('Should guard for Empty 2', () => {
enum E {}
const T = Type.Enum(E)
Assert.IsTrue(TypeGuard.IsNever(T))
})
// ----------------------------------------------------------------
// Enum
// ----------------------------------------------------------------
it('Should guard for TEnum Enum 0', () => {
enum E {}
const T = Type.Enum(E)
Assert.IsTrue(TypeGuard.IsNever(T))
})
it('Should guard for TEnum Enum 1', () => {
enum E {
A,
}
const T = Type.Enum(E)
Assert.IsTrue(TypeGuard.IsLiteral(T))
Assert.IsEqual(T.const, E.A)
})
it('Should guard for TEnum Enum 2', () => {
enum E {
A = 1,
B = 2,
C = 3,
}
const T = Type.Enum(E)
Assert.IsTrue(TypeGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, E.A)
Assert.IsEqual(T.anyOf[1].const, E.B)
Assert.IsEqual(T.anyOf[2].const, E.C)
})
it('Should guard for TEnum Enum 3', () => {
enum E {
A = 'X',
B = 'Y',
C = 'Z',
}
const T = Type.Enum(E)
Assert.IsTrue(TypeGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, E.A)
Assert.IsEqual(T.anyOf[1].const, E.B)
Assert.IsEqual(T.anyOf[2].const, E.C)
})
it('Should guard for TEnum Enum 4', () => {
enum E {
A = 'X',
B = 'Y',
C = 'X',
}
const T = Type.Enum(E)
Assert.IsTrue(TypeGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, E.A)
Assert.IsEqual(T.anyOf[1].const, E.B)
Assert.IsEqual(T.anyOf.length, 2)
})
// ----------------------------------------------------------------
// Object Literal
// ----------------------------------------------------------------
it('Should guard for TEnum Object Literal 0', () => {
const T = Type.Enum({})
Assert.IsTrue(TypeGuard.IsNever(T))
})
it('Should guard for TEnum Object Literal 1', () => {
const T = Type.Enum({ A: 1 })
Assert.IsTrue(TypeGuard.IsLiteral(T))
Assert.IsEqual(T.const, 1)
})
it('Should guard for TEnum Object Literal 2', () => {
const T = Type.Enum({
A: 1,
B: 2,
C: 3,
})
Assert.IsTrue(TypeGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 1)
Assert.IsEqual(T.anyOf[1].const, 2)
Assert.IsEqual(T.anyOf[2].const, 3)
})
it('Should guard for TEnum Object Literal 3', () => {
const T = Type.Enum({
A: 'X',
B: 'Y',
C: 'Z',
})
Assert.IsTrue(TypeGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 'X')
Assert.IsEqual(T.anyOf[1].const, 'Y')
Assert.IsEqual(T.anyOf[2].const, 'Z')
})
it('Should guard for TEnum Object Literal 4', () => {
const T = Type.Enum({
A: 'X',
B: 'Y',
C: 'X',
})
Assert.IsTrue(TypeGuard.IsUnion(T))
Assert.IsEqual(T.anyOf[0].const, 'X')
Assert.IsEqual(T.anyOf[1].const, 'Y')
Assert.IsEqual(T.anyOf.length, 2)
})
})

Some files were not shown because too many files have changed in this diff Show More