Skip to content

Commit

Permalink
Add Constructor Check, Create and Transform.Has
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 committed May 4, 2024
1 parent adcd66f commit f33388a
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 8 deletions.
32 changes: 25 additions & 7 deletions example/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
import { TypeSystem } from '@sinclair/typebox/system'
import { TypeCompiler } from '@sinclair/typebox/compiler'
import { Value, ValuePointer } from '@sinclair/typebox/value'
import { Type, TypeGuard, KindGuard, Kind, Static, TSchema } from '@sinclair/typebox'
import { Type, TypeRegistry, Kind, TSchema, SchemaOptions } from '@sinclair/typebox'
import { Value } from '@sinclair/typebox/value'

function Enum(value: unknown[]) {
return Type.FunctionCall(null, [], Type.Undefined())
// Tests:
// - Check
// - Create
// - Transform.Has
// Todo:
// - Propogation of This into nested Constructor / Function calls

export class Foo {
constructor(public a: number) {
console.log('Inside Consructor', a)
}
method(a: number) {
console.log('Inside Method', a, this)
}
}
// prettier-ignore
const T = Type.ConstructorCall([1], Type.Object({
method: Type.FunctionCall(null, [2], Type.Number())
}))

const C = Value.Create(T)

console.log(Value.Check(Enum([1, 2, 3]), () => { console.log('hmmm' )} ))
const X = new C(1)
console.log(X.method(12))

console.log(Value.Check(T, Foo))
12 changes: 11 additions & 1 deletion src/value/check/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import type { TBigInt } from '../../type/bigint/index'
import type { TBoolean } from '../../type/boolean/index'
import type { TDate } from '../../type/date/index'
import type { TConstructor } from '../../type/constructor/index'
import type { TConstructorCall } from '../../type/constructor-call/index'
import type { TFunction } from '../../type/function/index'
import type { TFunctionCall } from '../../type/function-call/index'
import type { TInteger } from '../../type/integer/index'
Expand Down Expand Up @@ -73,7 +74,7 @@ import type { TVoid } from '../../type/void/index'
// ------------------------------------------------------------------
// ValueGuard
// ------------------------------------------------------------------
import { IsArray, IsUint8Array, IsDate, IsPromise, IsFunction, IsAsyncIterator, IsIterator, IsBoolean, IsNumber, IsBigInt, IsString, IsSymbol, IsInteger, IsNull, IsUndefined } from '../guard/index'
import { IsArray, IsUint8Array, IsDate, IsPromise, IsFunction, IsAsyncIterator, IsIterator, IsBoolean, IsNumber, IsBigInt, IsString, IsSymbol, IsInteger, IsNull, IsUndefined, IsConstructor } from '../guard/index'
// ------------------------------------------------------------------
// TypeGuard
// ------------------------------------------------------------------
Expand Down Expand Up @@ -164,6 +165,13 @@ function FromBoolean(schema: TBoolean, references: TSchema[], value: any): boole
function FromConstructor(schema: TConstructor, references: TSchema[], value: any): boolean {
return Visit(schema.returns, references, value.prototype)
}
function FromConstructorCall(schema: TConstructorCall, references: TSchema[], value: any): boolean {
try {
return IsConstructor(value) && Visit(schema.constructorCall.returns, references, new value(...schema.constructorCall.parameters))
} catch (err) {
return false
}
}
function FromDate(schema: TDate, references: TSchema[], value: any): boolean {
if (!IsDate(value)) return false
if (IsDefined<number>(schema.exclusiveMaximumTimestamp) && !(value.getTime() < schema.exclusiveMaximumTimestamp)) {
Expand Down Expand Up @@ -438,6 +446,8 @@ function Visit<T extends TSchema>(schema: T, references: TSchema[], value: any):
return FromBoolean(schema_, references_, value)
case 'Constructor':
return FromConstructor(schema_, references_, value)
case 'ConstructorCall':
return FromConstructorCall(schema_, references_, value)
case 'Date':
return FromDate(schema_, references_, value)
case 'Function':
Expand Down
22 changes: 22 additions & 0 deletions src/value/create/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import type { TBigInt } from '../../type/bigint/index'
import type { TBoolean } from '../../type/boolean/index'
import type { TDate } from '../../type/date/index'
import type { TConstructor } from '../../type/constructor/index'
import type { TConstructorCall } from '../../type/constructor-call/index'
import type { TFunction } from '../../type/function/index'
import type { TFunctionCall } from '../../type/function-call/index'
import type { TInteger } from '../../type/integer/index'
Expand Down Expand Up @@ -150,6 +151,25 @@ function FromConstructor(schema: TConstructor, references: TSchema[]): any {
}
}
}
function FromConstructorCall(schema: TConstructorCall, references: TSchema[]): any {
if (HasPropertyKey(schema, 'default')) {
return FromDefault(schema.default)
} else {
const value = Visit(schema.constructorCall.returns, references) as any
if (typeof value === 'object' && !Array.isArray(value)) {
return class {
constructor() {
for (const [key, val] of Object.entries(value)) {
const self = this as any
self[key] = val
}
}
}
} else {
return class {}
}
}
}
function FromDate(schema: TDate, references: TSchema[]): any {
if (HasPropertyKey(schema, 'default')) {
return FromDefault(schema.default)
Expand Down Expand Up @@ -413,6 +433,8 @@ function Visit(schema: TSchema, references: TSchema[]): unknown {
return FromBoolean(schema_, references_)
case 'Constructor':
return FromConstructor(schema_, references_)
case 'ConstructorCall':
return FromConstructorCall(schema_, references_)
case 'Date':
return FromDate(schema_, references_)
case 'Function':
Expand Down
4 changes: 4 additions & 0 deletions src/value/guard/guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ export function IsString(value: unknown): value is string {
export function IsFunction(value: unknown): value is (...args: unknown[]) => unknown {
return typeof value === 'function'
}
/** Returns true if this value is a constructor */
export function IsConstructor(value: unknown): value is new (...args: unknown[]) => unknown {
return typeof value === 'function' && value.hasOwnProperty('prototype')
}
/** Returns true if this value is a symbol */
export function IsSymbol(value: unknown): value is symbol {
return typeof value === 'symbol'
Expand Down
7 changes: 7 additions & 0 deletions src/value/transform/has.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import type { TSchema } from '../../type/schema/index'
import type { TArray } from '../../type/array/index'
import type { TAsyncIterator } from '../../type/async-iterator/index'
import type { TConstructor } from '../../type/constructor/index'
import type { TConstructorCall } from '../../type/constructor-call/index'
import type { TFunction } from '../../type/function/index'
import type { TFunctionCall } from '../../type/function-call/index'
import type { TIntersect } from '../../type/intersect/index'
Expand Down Expand Up @@ -68,6 +69,10 @@ function FromConstructor(schema: TConstructor, references: TSchema[]) {
return IsTransform(schema) || Visit(schema.returns, references) || schema.parameters.some((schema) => Visit(schema, references))
}
// prettier-ignore
function FromConstructorCall(schema: TConstructorCall, references: TSchema[]) {
return IsTransform(schema) || Visit(schema.constructorCall.returns, references)
}
// prettier-ignore
function FromFunction(schema: TFunction, references: TSchema[]) {
return IsTransform(schema) || Visit(schema.returns, references) || schema.parameters.some((schema) => Visit(schema, references))
}
Expand Down Expand Up @@ -138,6 +143,8 @@ function Visit(schema: TSchema, references: TSchema[]): boolean {
return FromAsyncIterator(schema_, references_)
case 'Constructor':
return FromConstructor(schema_, references_)
case 'ConstructorCall':
return FromConstructorCall(schema_, references_)
case 'Function':
return FromFunction(schema_, references_)
case 'FunctionCall':
Expand Down

0 comments on commit f33388a

Please sign in to comment.