Skip to content

Commit

Permalink
Optimizations Across Types and Value modules
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 committed Apr 25, 2024
1 parent 3fca39b commit 7da77f0
Show file tree
Hide file tree
Showing 32 changed files with 156 additions and 178 deletions.
26 changes: 13 additions & 13 deletions example/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { Type } from '@sinclair/typebox'
import { Value } from '@sinclair/typebox/value'

const K = Type.TemplateLiteral('p${0|1}${0|1}${0|1}${0|1}${0|1}${0|1}')
const T = Type.Mapped(K, _ => Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number()
}))

const S = Date.now()
for(let i = 0; i < 1000; i++) {
const K = Type.TemplateLiteral('p${0|1}${0|1}${0|1}${0|1}${0|1}${0|1}')
const T = Type.Mapped(K, _ => Type.Object({
const T = Type.Transform(
Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number()
}))
z: Type.Number(),
}),
)
.Decode((value) => value)
.Encode((value) => value)

const S = Date.now()
for (let i = 0; i < 1_000_000; i++) {
const R = Value.Decode(T, { x: 1, y: 2, z: 3 })
Value.Encode(T, R)
}
console.log(Date.now() - S)
4 changes: 2 additions & 2 deletions src/type/clone/value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ function RegExpType(value: RegExp) {
}
function ObjectType(value: Record<keyof any, unknown>) {
const result = {} as Record<PropertyKey, unknown>
for(const key of Object.getOwnPropertyNames(value)) {
for (const key of Object.getOwnPropertyNames(value)) {
result[key] = Visit(value[key])
}
for(const key of Object.getOwnPropertySymbols(value)) {
for (const key of Object.getOwnPropertySymbols(value)) {
result[key] = Visit(value[key])
}
return result
Expand Down
14 changes: 6 additions & 8 deletions src/type/composite/composite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ type TCompositeKeys<T extends TSchema[], Acc extends PropertyKey[] = []> = (
)
// prettier-ignore
function CompositeKeys<T extends TSchema[]>(T: [...T]): TCompositeKeys<T> {
return SetDistinct(T.reduce((Acc, L) => {
Acc.push(...KeyOfPropertyKeys(L))
return Acc
}, [] as PropertyKey[])) as never
const Acc = [] as PropertyKey[]
for(const L of T) Acc.push(...KeyOfPropertyKeys(L))
return SetDistinct(Acc) as never
}
// ------------------------------------------------------------------
// FilterNever
Expand Down Expand Up @@ -81,10 +80,9 @@ type TCompositeProperty<T extends TSchema[], K extends PropertyKey, Acc extends
)
// prettier-ignore
function CompositeProperty<T extends TSchema[], K extends PropertyKey>(T: [...T], K: K): TCompositeProperty<T, K> {
return FilterNever(T.reduce((Acc, L) => {
Acc.push(...IndexFromPropertyKeys(L, [K]))
return Acc
}, [] as TSchema[])) as never
const Acc = [] as TSchema[]
for(const L of T) Acc.push(...IndexFromPropertyKeys(L, [K]))
return FilterNever(Acc) as never
}
// ------------------------------------------------------------------
// CompositeProperties
Expand Down
6 changes: 3 additions & 3 deletions src/type/const/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ type TFromProperties<T extends Record<PropertyKey, unknown>> = {
}
// prettier-ignore
function FromProperties<T extends Record<PropertyKey, unknown>>(value: T): TFromProperties<T> {
return globalThis.Object.getOwnPropertyNames(value).reduce((acc, key) => {
return { ...acc, [key]: Readonly(FromValue(value[key], false)) }
}, {} as TProperties) as unknown as TFromProperties<T>
const Acc = {} as TProperties
for(const K of globalThis.Object.getOwnPropertyNames(value)) Acc[K] = Readonly(FromValue(value[K], false))
return Acc as never
}
// ------------------------------------------------------------------
// ConditionalReadonly - Only applied if not root
Expand Down
6 changes: 3 additions & 3 deletions src/type/deref/deref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ type FromProperties<T extends TProperties> = Evaluate<{
}>
// prettier-ignore
function FromProperties(properties: TProperties, references: TSchema[]) {
return globalThis.Object.getOwnPropertyNames(properties).reduce((acc, key) => {
return {...acc, [key]: Deref(properties[key], references) }
}, {} as TProperties)
const Acc = {} as TProperties
for(const K of globalThis.Object.getOwnPropertyNames(properties)) Acc[K] = Deref(properties[K], references)
return Acc as never
}
// prettier-ignore
function FromConstructor(schema: TConstructor, references: TSchema[]) {
Expand Down
6 changes: 3 additions & 3 deletions src/type/exclude/exclude-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ function FromProperties<
P extends TProperties,
T extends TSchema
>(P: P, U: T): TFromProperties<P, T> {
return globalThis.Object.getOwnPropertyNames(P).reduce((Acc, K2) => {
return {...Acc, [K2]: Exclude(P[K2], U) }
}, {}) as TFromProperties<P, T>
const Acc = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Exclude(P[K2], U)
return Acc as never
}
// ------------------------------------------------------------------
// FromMappedResult
Expand Down
6 changes: 3 additions & 3 deletions src/type/extends/extends-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ function FromProperties<
True extends TSchema,
False extends TSchema
>(P: P, Right: Right, True: True, False: False, options: SchemaOptions): TFromProperties<P, Right, True, False> {
return globalThis.Object.getOwnPropertyNames(P).reduce((Acc, K2) => {
return {...Acc, [K2]: Extends(P[K2], Right, True, False, options) }
}, {}) as TFromProperties<P, Right, True, False>
const Acc = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Extends(P[K2], Right, True, False, options)
return Acc as never
}
// ------------------------------------------------------------------
// FromMappedResult
Expand Down
6 changes: 3 additions & 3 deletions src/type/extract/extract-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ function FromProperties<
P extends TProperties,
T extends TSchema
>(P: P, T: T): TFromProperties<P, T> {
return globalThis.Object.getOwnPropertyNames(P).reduce((Acc, K2) => {
return {...Acc, [K2]: Extract(P[K2], T) }
}, {}) as TFromProperties<P, T>
const Acc = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Extract(P[K2], T)
return Acc as never
}
// ------------------------------------------------------------------
// FromMappedResult
Expand Down
6 changes: 3 additions & 3 deletions src/type/indexed/indexed-property-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ type TFromUnion<T extends TSchema[], Acc extends string[] = []> = (
)
// prettier-ignore
function FromUnion<T extends TSchema[]>(T: T): TFromUnion<T> {
return T.reduce((Acc, L) => {
return [...Acc, ...IndexPropertyKeys(L)]
}, [] as string[]) as TFromUnion<T>
const Acc = [] as string[]
for(const L of T) Acc.push(...IndexPropertyKeys(L))
return Acc as never
}
// ------------------------------------------------------------------
// FromLiteral
Expand Down
6 changes: 3 additions & 3 deletions src/type/keyof/keyof-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ type TFromProperties<
function FromProperties<
K extends TProperties
>(K: K, options: SchemaOptions): TFromProperties<K> {
return globalThis.Object.getOwnPropertyNames(K).reduce((Acc, K2) => {
return {...Acc, [K2]: KeyOf(K[K2], options) }
}, {}) as TFromProperties<K>
const Acc = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(K)) Acc[K2] = KeyOf(K[K2], options)
return Acc as never
}
// ------------------------------------------------------------------
// FromMappedResult
Expand Down
6 changes: 3 additions & 3 deletions src/type/keyof/keyof-property-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ type TFromRest<T extends TSchema[], Acc extends PropertyKey[][] = []> = (
)
// prettier-ignore
function FromRest<T extends TSchema[]>(T: [...T]): TFromRest<T> {
return T.reduce((Acc, L) => {
return [...Acc, KeyOfPropertyKeys(L)]
}, [] as PropertyKey[][]) as TFromRest<T>
const Acc = [] as PropertyKey[][]
for(const L of T) Acc.push(KeyOfPropertyKeys(L))
return Acc as never
}
// ------------------------------------------------------------------
// FromIntersect
Expand Down
19 changes: 1 addition & 18 deletions src/type/mapped/mapped.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,24 +55,7 @@ import type { TMappedKey } from './mapped-key'
// ------------------------------------------------------------------
// TypeGuard
// ------------------------------------------------------------------
// prettier-ignore
import {
IsArray,
IsAsyncIterator,
IsConstructor,
IsFunction,
IsIntersect,
IsIterator,
IsReadonly,
IsMappedResult,
IsMappedKey,
IsObject,
IsOptional,
IsPromise,
IsSchema,
IsTuple,
IsUnion,
} from '../guard/type'
import { IsArray, IsAsyncIterator, IsConstructor, IsFunction, IsIntersect, IsIterator, IsReadonly, IsMappedResult, IsMappedKey, IsObject, IsOptional, IsPromise, IsSchema, IsTuple, IsUnion } from '../guard/type'
// ------------------------------------------------------------------
// FromMappedResult
//
Expand Down
11 changes: 7 additions & 4 deletions src/type/object/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,13 @@ function _Object<T extends TProperties>(properties: T, options: ObjectOptions =
const optionalKeys = propertyKeys.filter((key) => IsOptional(properties[key]))
const requiredKeys = propertyKeys.filter((name) => !optionalKeys.includes(name))
const clonedAdditionalProperties = IsSchema(options.additionalProperties) ? { additionalProperties: CloneType(options.additionalProperties) } : {}
const clonedProperties = propertyKeys.reduce((acc, key) => ({ ...acc, [key]: CloneType(properties[key]) }), {} as TProperties)
return (requiredKeys.length > 0
? { ...options, ...clonedAdditionalProperties, [Kind]: 'Object', type: 'object', properties: clonedProperties, required: requiredKeys }
: { ...options, ...clonedAdditionalProperties, [Kind]: 'Object', type: 'object', properties: clonedProperties }) as unknown as TObject<T>
const clonedProperties = {} as Record<PropertyKey, TSchema>
for (const key of propertyKeys) clonedProperties[key] = CloneType(properties[key])
return (
requiredKeys.length > 0
? { ...options, ...clonedAdditionalProperties, [Kind]: 'Object', type: 'object', properties: clonedProperties, required: requiredKeys }
: { ...options, ...clonedAdditionalProperties, [Kind]: 'Object', type: 'object', properties: clonedProperties }
) as never
}

/** `[Json]` Creates an Object type */
Expand Down
6 changes: 3 additions & 3 deletions src/type/omit/omit-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ function FromProperties<
P extends TProperties,
K extends PropertyKey[],
>(P: P, K: [...K], options: SchemaOptions): TFromProperties<P, K> {
return globalThis.Object.getOwnPropertyNames(P).reduce((Acc, K2) => {
return {...Acc, [K2]: Omit(P[K2], K, options) }
}, {}) as TFromProperties<P, K>
const Acc = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Omit(P[K2], K, options)
return Acc as never
}
// ------------------------------------------------------------------
// FromMappedResult
Expand Down
6 changes: 3 additions & 3 deletions src/type/optional/optional-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ function FromProperties<
P extends TProperties,
F extends boolean,
>(P: P, F: F): TFromProperties<P, F> {
return globalThis.Object.getOwnPropertyNames(P).reduce((Acc, K2) => {
return {...Acc, [K2]: Optional(P[K2], F) }
}, {}) as TFromProperties<P, F>
const Acc = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Optional(P[K2], F)
return Acc as never
}
// ------------------------------------------------------------------
// FromMappedResult
Expand Down
6 changes: 3 additions & 3 deletions src/type/partial/partial-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ type TFromProperties<
function FromProperties<
P extends TProperties
>(K: P, options: SchemaOptions): TFromProperties<P> {
return globalThis.Object.getOwnPropertyNames(K).reduce((Acc, K2) => {
return {...Acc, [K2]: Partial(K[K2], options) }
}, {}) as TFromProperties<P>
const Acc = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(K)) Acc[K2] = Partial(K[K2], options)
return Acc as never
}
// ------------------------------------------------------------------
// FromMappedResult
Expand Down
8 changes: 4 additions & 4 deletions src/type/partial/partial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ type TFromProperties<T extends TProperties> = Evaluate<{
TOptional<T[K]>
}>
// prettier-ignore
function FromProperties<T extends TProperties>(T: T) {
return globalThis.Object.getOwnPropertyNames(T).reduce((Acc, K) => {
return { ...Acc, [K]: Optional(T[K]) }
}, {} as TProperties)
function FromProperties<T extends TProperties>(T: T): TFromProperties<T> {
const Acc = {} as TProperties
for(const K of globalThis.Object.getOwnPropertyNames(T)) Acc[K] = Optional(T[K])
return Acc as never
}
// ------------------------------------------------------------------
// PartialResolve
Expand Down
6 changes: 3 additions & 3 deletions src/type/pick/pick-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ function FromProperties<
P extends TProperties,
K extends PropertyKey[],
>(P: P, K: [...K], options: SchemaOptions): TFromProperties<P, K> {
return globalThis.Object.getOwnPropertyNames(P).reduce((Acc, K2) => {
return {...Acc, [K2]: Pick(P[K2], K, options) }
}, {}) as TFromProperties<P, K>
const Acc = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Pick(P[K2], K, options)
return Acc as never
}
// ------------------------------------------------------------------
// FromMappedResult
Expand Down
8 changes: 4 additions & 4 deletions src/type/pick/pick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import type { TupleToUnion, Evaluate } from '../helpers/index'
import { type TRecursive } from '../recursive/index'
import { type TIntersect, Intersect } from '../intersect/index'
import { type TUnion, Union } from '../union/index'
import { type TObject, type TProperties, Object } from '../object/index'
import { type TObject, type TProperties, type TPropertyKey, Object } from '../object/index'
import type { TMappedKey, TMappedResult } from '../mapped/index'
import { IndexPropertyKeys, type TIndexPropertyKeys } from '../indexed/index'
import { Discard } from '../discard/index'
Expand Down Expand Up @@ -74,9 +74,9 @@ function FromUnion<T extends TSchema[], K extends PropertyKey[]>(T: T, K: K) {
type FromProperties<T extends TProperties, K extends PropertyKey[], I extends PropertyKey = TupleToUnion<K>> = Evaluate<Pick<T, I & keyof T>>
// prettier-ignore
function FromProperties<T extends TProperties, K extends PropertyKey[]>(T: T, K: K) {
return K.reduce((Acc, K) => {
return K in T ? { ...Acc, [K]: T[K as keyof T] } : Acc
}, {})
const Acc = {} as TProperties
for(const K2 of K) if(K2 in T) Acc[K2 as TPropertyKey] = T[K2 as keyof T]
return Acc as never
}
// ------------------------------------------------------------------
// PickResolve
Expand Down
2 changes: 1 addition & 1 deletion src/type/readonly-optional/readonly-optional.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ export type TReadonlyOptional<T extends TSchema> = TOptional<T> & TReadonly<T>

/** `[Json]` Creates a Readonly and Optional property */
export function ReadonlyOptional<T extends TSchema>(schema: T): TReadonly<TOptional<T>> {
return Readonly(Optional(schema)) as TReadonly<TOptional<T>>
return Readonly(Optional(schema)) as never
}
6 changes: 3 additions & 3 deletions src/type/readonly/readonly-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ function FromProperties<
P extends TProperties,
F extends boolean,
>(K: P, F: F): TFromProperties<P, F> {
return globalThis.Object.getOwnPropertyNames(K).reduce((Acc, K2) => {
return {...Acc, [K2]: Readonly(K[K2], F) }
}, {}) as TFromProperties<P, F>
const Acc = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(K)) Acc[K2] = Readonly(K[K2], F)
return Acc as never
}
// ------------------------------------------------------------------
// FromMappedResult
Expand Down
5 changes: 3 additions & 2 deletions src/type/record/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ function RecordCreateFromPattern(pattern: string, T: TSchema, options: ObjectOpt
// ------------------------------------------------------------------
// prettier-ignore
function RecordCreateFromKeys(K: string[], T: TSchema, options: ObjectOptions): TObject<TProperties> {
const P = K.reduce((Acc, K) => ({ ...Acc, [K]: CloneType(T) }), {} as TProperties)
return Object(P, { ...options, [Hint]: 'Record' })
const Acc = {} as TProperties
for(const K2 of K) Acc[K2] = CloneType(T)
return Object(Acc, { ...options, [Hint]: 'Record' })
}
// ------------------------------------------------------------------
// FromTemplateLiteralKey (Fast Inference)
Expand Down
6 changes: 3 additions & 3 deletions src/type/required/required-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ type TFromProperties<
function FromProperties<
P extends TProperties
>(P: P, options: SchemaOptions): TFromProperties<P> {
return globalThis.Object.getOwnPropertyNames(P).reduce((Acc, K2) => {
return {...Acc, [K2]: Required(P[K2], options) }
}, {}) as TFromProperties<P>
const Acc = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Required(P[K2], options)
return Acc as never
}
// ------------------------------------------------------------------
// FromMappedResult
Expand Down
6 changes: 3 additions & 3 deletions src/type/required/required.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ type TFromProperties<T extends TProperties> = Evaluate<{
}>
// prettier-ignore
function FromProperties<T extends TProperties>(T: T) {
return globalThis.Object.getOwnPropertyNames(T).reduce((Acc, K) => {
return { ...Acc, [K]: Discard(T[K], [OptionalKind]) as TSchema }
}, {} as TProperties)
const Acc = {} as TProperties
for(const K of globalThis.Object.getOwnPropertyNames(T)) Acc[K] = Discard(T[K], [OptionalKind]) as TSchema
return Acc as never
}
// ------------------------------------------------------------------
// RequiredResolve
Expand Down
6 changes: 3 additions & 3 deletions src/type/rest/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ type TRestResolve<T extends TSchema> =
// prettier-ignore
function RestResolve<T extends TSchema>(T: T) {
return (
IsIntersect(T) ? [...T.allOf] :
IsUnion(T) ? [...T.anyOf] :
IsTuple(T) ? [...(T.items ?? [])] :
IsIntersect(T) ? CloneRest(T.allOf) :
IsUnion(T) ? CloneRest(T.anyOf) :
IsTuple(T) ? CloneRest(T.items ?? []) :
[]
) as TRestResolve<T>
}
Expand Down
4 changes: 3 additions & 1 deletion src/type/sets/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,7 @@ export type TSetUnionMany<T extends PropertyKey[][], Acc extends PropertyKey[] =
)
/** Returns the Union of multiple sets */
export function SetUnionMany<T extends PropertyKey[][]>(T: [...T]): TSetUnionMany<T> {
return T.reduce((Acc, L) => [...Acc, ...L], [] as PropertyKey[]) as TSetUnionMany<T>
const Acc = [] as PropertyKey[]
for (const L of T) Acc.push(...L)
return Acc as never
}
2 changes: 1 addition & 1 deletion src/value/clean/clean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function FromObject(schema: TObject, references: TSchema[], value: unknown): any
function FromRecord(schema: TRecord, references: TSchema[], value: unknown): any {
if (!IsObject(value)) return value
const additionalProperties = schema.additionalProperties as TSchema
const propertyKeys = Object.keys(value)
const propertyKeys = Object.getOwnPropertyNames(value)
const [propertyKey, propertySchema] = Object.entries(schema.patternProperties)[0]
const propertyKeyTest = new RegExp(propertyKey)
for (const key of propertyKeys) {
Expand Down

0 comments on commit 7da77f0

Please sign in to comment.