Publish
This commit is contained in:
665
src/compiler/compiler.ts
Normal file
665
src/compiler/compiler.ts
Normal file
@@ -0,0 +1,665 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/compiler
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { TransformEncode, TransformDecode, HasTransform, TransformDecodeCheckError, TransformEncodeCheckError } from '../value/transform/index'
|
||||
import { Errors, ValueErrorIterator } from '../errors/index'
|
||||
import { TypeSystemPolicy } from '../system/index'
|
||||
import { TypeBoxError } from '../type/error/index'
|
||||
import { Deref } from '../value/deref/index'
|
||||
import { Hash } from '../value/hash/index'
|
||||
import { Kind } from '../type/symbols/index'
|
||||
|
||||
import { TypeRegistry, FormatRegistry } from '../type/registry/index'
|
||||
import { KeyOfPattern } from '../type/keyof/index'
|
||||
import { ExtendsUndefinedCheck } from '../type/extends/extends-undefined'
|
||||
|
||||
import type { TSchema } from '../type/schema/index'
|
||||
import type { TAsyncIterator } from '../type/async-iterator/index'
|
||||
import type { TAny } from '../type/any/index'
|
||||
import type { TArgument } from '../type/argument/index'
|
||||
import type { TArray } from '../type/array/index'
|
||||
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 { TFunction } from '../type/function/index'
|
||||
import type { TImport } from '../type/module/index'
|
||||
import type { TInteger } from '../type/integer/index'
|
||||
import type { TIntersect } from '../type/intersect/index'
|
||||
import type { TIterator } from '../type/iterator/index'
|
||||
import type { TLiteral } from '../type/literal/index'
|
||||
import { Never, type TNever } from '../type/never/index'
|
||||
import type { TNot } from '../type/not/index'
|
||||
import type { TNull } from '../type/null/index'
|
||||
import type { TNumber } from '../type/number/index'
|
||||
import type { TObject } from '../type/object/index'
|
||||
import type { TPromise } from '../type/promise/index'
|
||||
import type { TRecord } from '../type/record/index'
|
||||
import { Ref, type TRef } from '../type/ref/index'
|
||||
import type { TRegExp } from '../type/regexp/index'
|
||||
import type { TTemplateLiteral } from '../type/template-literal/index'
|
||||
import type { TThis } from '../type/recursive/index'
|
||||
import type { TTuple } from '../type/tuple/index'
|
||||
import type { TUnion } from '../type/union/index'
|
||||
import type { TUnknown } from '../type/unknown/index'
|
||||
import type { Static, StaticDecode, StaticEncode } from '../type/static/index'
|
||||
import type { TString } from '../type/string/index'
|
||||
import type { TSymbol } from '../type/symbol/index'
|
||||
import type { TUndefined } from '../type/undefined/index'
|
||||
import type { TUint8Array } from '../type/uint8array/index'
|
||||
import type { TVoid } from '../type/void/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ValueGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsArray, IsString, IsNumber, IsBigInt } from '../value/guard/index'
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsSchema } from '../type/guard/type'
|
||||
// ------------------------------------------------------------------
|
||||
// CheckFunction
|
||||
// ------------------------------------------------------------------
|
||||
export type CheckFunction = (value: unknown) => boolean
|
||||
// ------------------------------------------------------------------
|
||||
// TypeCheck
|
||||
// ------------------------------------------------------------------
|
||||
export class TypeCheck<T extends TSchema> {
|
||||
private readonly hasTransform: boolean
|
||||
constructor(private readonly schema: T, private readonly references: TSchema[], private readonly checkFunc: CheckFunction, private readonly code: string) {
|
||||
this.hasTransform = HasTransform(schema, references)
|
||||
}
|
||||
/** Returns the generated assertion code used to validate this type. */
|
||||
public Code(): string {
|
||||
return this.code
|
||||
}
|
||||
/** Returns the schema type used to validate */
|
||||
public Schema(): T {
|
||||
return this.schema
|
||||
}
|
||||
/** Returns reference types used to validate */
|
||||
public References(): TSchema[] {
|
||||
return this.references
|
||||
}
|
||||
/** Returns an iterator for each error in this value. */
|
||||
public Errors(value: unknown): ValueErrorIterator {
|
||||
return Errors(this.schema, this.references, value)
|
||||
}
|
||||
/** Returns true if the value matches the compiled type. */
|
||||
public Check(value: unknown): value is Static<T> {
|
||||
return this.checkFunc(value)
|
||||
}
|
||||
/** Decodes a value or throws if error */
|
||||
public Decode<Static = StaticDecode<T>, Result extends Static = Static>(value: unknown): Result {
|
||||
if (!this.checkFunc(value)) throw new TransformDecodeCheckError(this.schema, value, this.Errors(value).First()!)
|
||||
return (this.hasTransform ? TransformDecode(this.schema, this.references, value) : value) as never
|
||||
}
|
||||
/** Encodes a value or throws if error */
|
||||
public Encode<Static = StaticEncode<T>, Result extends Static = Static>(value: unknown): Result {
|
||||
const encoded = this.hasTransform ? TransformEncode(this.schema, this.references, value) : value
|
||||
if (!this.checkFunc(encoded)) throw new TransformEncodeCheckError(this.schema, value, this.Errors(value).First()!)
|
||||
return encoded as never
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Character
|
||||
// ------------------------------------------------------------------
|
||||
namespace Character {
|
||||
export function DollarSign(code: number) {
|
||||
return code === 36
|
||||
}
|
||||
export function IsUnderscore(code: number) {
|
||||
return code === 95
|
||||
}
|
||||
export function IsAlpha(code: number) {
|
||||
return (code >= 65 && code <= 90) || (code >= 97 && code <= 122)
|
||||
}
|
||||
export function IsNumeric(code: number) {
|
||||
return code >= 48 && code <= 57
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// MemberExpression
|
||||
// ------------------------------------------------------------------
|
||||
namespace MemberExpression {
|
||||
function IsFirstCharacterNumeric(value: string) {
|
||||
if (value.length === 0) return false
|
||||
return Character.IsNumeric(value.charCodeAt(0))
|
||||
}
|
||||
function IsAccessor(value: string) {
|
||||
if (IsFirstCharacterNumeric(value)) return false
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const code = value.charCodeAt(i)
|
||||
const check = Character.IsAlpha(code) || Character.IsNumeric(code) || Character.DollarSign(code) || Character.IsUnderscore(code)
|
||||
if (!check) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
function EscapeHyphen(key: string) {
|
||||
return key.replace(/'/g, "\\'")
|
||||
}
|
||||
export function Encode(object: string, key: string) {
|
||||
return IsAccessor(key) ? `${object}.${key}` : `${object}['${EscapeHyphen(key)}']`
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Identifier
|
||||
// ------------------------------------------------------------------
|
||||
namespace Identifier {
|
||||
export function Encode($id: string) {
|
||||
const buffer: string[] = []
|
||||
for (let i = 0; i < $id.length; i++) {
|
||||
const code = $id.charCodeAt(i)
|
||||
if (Character.IsNumeric(code) || Character.IsAlpha(code)) {
|
||||
buffer.push($id.charAt(i))
|
||||
} else {
|
||||
buffer.push(`_${code}_`)
|
||||
}
|
||||
}
|
||||
return buffer.join('').replace(/__/g, '_')
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// LiteralString
|
||||
// ------------------------------------------------------------------
|
||||
namespace LiteralString {
|
||||
export function Escape(content: string) {
|
||||
return content.replace(/'/g, "\\'")
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Errors
|
||||
// ------------------------------------------------------------------
|
||||
export class TypeCompilerUnknownTypeError extends TypeBoxError {
|
||||
constructor(public readonly schema: TSchema) {
|
||||
super('Unknown type')
|
||||
}
|
||||
}
|
||||
export class TypeCompilerTypeGuardError extends TypeBoxError {
|
||||
constructor(public readonly schema: TSchema) {
|
||||
super('Preflight validation check failed to guard for the given schema')
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Policy
|
||||
// ------------------------------------------------------------------
|
||||
export namespace Policy {
|
||||
export function IsExactOptionalProperty(value: string, key: string, expression: string) {
|
||||
return TypeSystemPolicy.ExactOptionalPropertyTypes ? `('${key}' in ${value} ? ${expression} : true)` : `(${MemberExpression.Encode(value, key)} !== undefined ? ${expression} : true)`
|
||||
}
|
||||
export function IsObjectLike(value: string): string {
|
||||
return !TypeSystemPolicy.AllowArrayObject ? `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}))` : `(typeof ${value} === 'object' && ${value} !== null)`
|
||||
}
|
||||
export function IsRecordLike(value: string): string {
|
||||
return !TypeSystemPolicy.AllowArrayObject
|
||||
? `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}) && !(${value} instanceof Date) && !(${value} instanceof Uint8Array))`
|
||||
: `(typeof ${value} === 'object' && ${value} !== null && !(${value} instanceof Date) && !(${value} instanceof Uint8Array))`
|
||||
}
|
||||
export function IsNumberLike(value: string): string {
|
||||
return TypeSystemPolicy.AllowNaN ? `typeof ${value} === 'number'` : `Number.isFinite(${value})`
|
||||
}
|
||||
export function IsVoidLike(value: string): string {
|
||||
return TypeSystemPolicy.AllowNullVoid ? `(${value} === undefined || ${value} === null)` : `${value} === undefined`
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TypeCompiler
|
||||
// ------------------------------------------------------------------
|
||||
export type TypeCompilerLanguageOption = 'typescript' | 'javascript'
|
||||
export interface TypeCompilerCodegenOptions {
|
||||
language?: TypeCompilerLanguageOption
|
||||
}
|
||||
/** Compiles Types for Runtime Type Checking */
|
||||
export namespace TypeCompiler {
|
||||
// ----------------------------------------------------------------
|
||||
// Guards
|
||||
// ----------------------------------------------------------------
|
||||
function IsAnyOrUnknown(schema: TSchema) {
|
||||
return schema[Kind] === 'Any' || schema[Kind] === 'Unknown'
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// Types
|
||||
// ----------------------------------------------------------------
|
||||
function* FromAny(schema: TAny, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield 'true'
|
||||
}
|
||||
function* FromArgument(schema: TArgument, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield 'true'
|
||||
}
|
||||
function* FromArray(schema: TArray, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `Array.isArray(${value})`
|
||||
const [parameter, accumulator] = [CreateParameter('value', 'any'), CreateParameter('acc', 'number')]
|
||||
if (IsNumber(schema.maxItems)) yield `${value}.length <= ${schema.maxItems}`
|
||||
if (IsNumber(schema.minItems)) yield `${value}.length >= ${schema.minItems}`
|
||||
const elementExpression = CreateExpression(schema.items, references, 'value')
|
||||
yield `${value}.every((${parameter}) => ${elementExpression})`
|
||||
if (IsSchema(schema.contains) || IsNumber(schema.minContains) || IsNumber(schema.maxContains)) {
|
||||
const containsSchema = IsSchema(schema.contains) ? schema.contains : Never()
|
||||
const checkExpression = CreateExpression(containsSchema, references, 'value')
|
||||
const checkMinContains = IsNumber(schema.minContains) ? [`(count >= ${schema.minContains})`] : []
|
||||
const checkMaxContains = IsNumber(schema.maxContains) ? [`(count <= ${schema.maxContains})`] : []
|
||||
const checkCount = `const count = value.reduce((${accumulator}, ${parameter}) => ${checkExpression} ? acc + 1 : acc, 0)`
|
||||
const check = [`(count > 0)`, ...checkMinContains, ...checkMaxContains].join(' && ')
|
||||
yield `((${parameter}) => { ${checkCount}; return ${check}})(${value})`
|
||||
}
|
||||
if (schema.uniqueItems === true) {
|
||||
const check = `const hashed = hash(element); if(set.has(hashed)) { return false } else { set.add(hashed) } } return true`
|
||||
const block = `const set = new Set(); for(const element of value) { ${check} }`
|
||||
yield `((${parameter}) => { ${block} )(${value})`
|
||||
}
|
||||
}
|
||||
function* FromAsyncIterator(schema: TAsyncIterator, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof value === 'object' && Symbol.asyncIterator in ${value})`
|
||||
}
|
||||
function* FromBigInt(schema: TBigInt, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'bigint')`
|
||||
if (IsBigInt(schema.exclusiveMaximum)) yield `${value} < BigInt(${schema.exclusiveMaximum})`
|
||||
if (IsBigInt(schema.exclusiveMinimum)) yield `${value} > BigInt(${schema.exclusiveMinimum})`
|
||||
if (IsBigInt(schema.maximum)) yield `${value} <= BigInt(${schema.maximum})`
|
||||
if (IsBigInt(schema.minimum)) yield `${value} >= BigInt(${schema.minimum})`
|
||||
if (IsBigInt(schema.multipleOf)) yield `(${value} % BigInt(${schema.multipleOf})) === 0`
|
||||
}
|
||||
function* FromBoolean(schema: TBoolean, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'boolean')`
|
||||
}
|
||||
function* FromConstructor(schema: TConstructor, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield* Visit(schema.returns, references, `${value}.prototype`)
|
||||
}
|
||||
function* FromDate(schema: TDate, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(${value} instanceof Date) && Number.isFinite(${value}.getTime())`
|
||||
if (IsNumber(schema.exclusiveMaximumTimestamp)) yield `${value}.getTime() < ${schema.exclusiveMaximumTimestamp}`
|
||||
if (IsNumber(schema.exclusiveMinimumTimestamp)) yield `${value}.getTime() > ${schema.exclusiveMinimumTimestamp}`
|
||||
if (IsNumber(schema.maximumTimestamp)) yield `${value}.getTime() <= ${schema.maximumTimestamp}`
|
||||
if (IsNumber(schema.minimumTimestamp)) yield `${value}.getTime() >= ${schema.minimumTimestamp}`
|
||||
if (IsNumber(schema.multipleOfTimestamp)) yield `(${value}.getTime() % ${schema.multipleOfTimestamp}) === 0`
|
||||
}
|
||||
function* FromFunction(schema: TFunction, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'function')`
|
||||
}
|
||||
function* FromImport(schema: TImport, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const members = globalThis.Object.getOwnPropertyNames(schema.$defs).reduce((result, key) => {
|
||||
return [...result, schema.$defs[key as never] as TSchema]
|
||||
}, [] as TSchema[])
|
||||
yield* Visit(Ref(schema.$ref), [...references, ...members], value)
|
||||
}
|
||||
function* FromInteger(schema: TInteger, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `Number.isInteger(${value})`
|
||||
if (IsNumber(schema.exclusiveMaximum)) yield `${value} < ${schema.exclusiveMaximum}`
|
||||
if (IsNumber(schema.exclusiveMinimum)) yield `${value} > ${schema.exclusiveMinimum}`
|
||||
if (IsNumber(schema.maximum)) yield `${value} <= ${schema.maximum}`
|
||||
if (IsNumber(schema.minimum)) yield `${value} >= ${schema.minimum}`
|
||||
if (IsNumber(schema.multipleOf)) yield `(${value} % ${schema.multipleOf}) === 0`
|
||||
}
|
||||
function* FromIntersect(schema: TIntersect, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const check1 = schema.allOf.map((schema: TSchema) => CreateExpression(schema, references, value)).join(' && ')
|
||||
if (schema.unevaluatedProperties === false) {
|
||||
const keyCheck = CreateVariable(`${new RegExp(KeyOfPattern(schema))};`)
|
||||
const check2 = `Object.getOwnPropertyNames(${value}).every(key => ${keyCheck}.test(key))`
|
||||
yield `(${check1} && ${check2})`
|
||||
} else if (IsSchema(schema.unevaluatedProperties)) {
|
||||
const keyCheck = CreateVariable(`${new RegExp(KeyOfPattern(schema))};`)
|
||||
const check2 = `Object.getOwnPropertyNames(${value}).every(key => ${keyCheck}.test(key) || ${CreateExpression(schema.unevaluatedProperties, references, `${value}[key]`)})`
|
||||
yield `(${check1} && ${check2})`
|
||||
} else {
|
||||
yield `(${check1})`
|
||||
}
|
||||
}
|
||||
function* FromIterator(schema: TIterator, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof value === 'object' && Symbol.iterator in ${value})`
|
||||
}
|
||||
function* FromLiteral(schema: TLiteral, references: TSchema[], value: string): IterableIterator<string> {
|
||||
if (typeof schema.const === 'number' || typeof schema.const === 'boolean') {
|
||||
yield `(${value} === ${schema.const})`
|
||||
} else {
|
||||
yield `(${value} === '${LiteralString.Escape(schema.const)}')`
|
||||
}
|
||||
}
|
||||
function* FromNever(schema: TNever, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `false`
|
||||
}
|
||||
function* FromNot(schema: TNot, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const expression = CreateExpression(schema.not, references, value)
|
||||
yield `(!${expression})`
|
||||
}
|
||||
function* FromNull(schema: TNull, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(${value} === null)`
|
||||
}
|
||||
function* FromNumber(schema: TNumber, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield Policy.IsNumberLike(value)
|
||||
if (IsNumber(schema.exclusiveMaximum)) yield `${value} < ${schema.exclusiveMaximum}`
|
||||
if (IsNumber(schema.exclusiveMinimum)) yield `${value} > ${schema.exclusiveMinimum}`
|
||||
if (IsNumber(schema.maximum)) yield `${value} <= ${schema.maximum}`
|
||||
if (IsNumber(schema.minimum)) yield `${value} >= ${schema.minimum}`
|
||||
if (IsNumber(schema.multipleOf)) yield `(${value} % ${schema.multipleOf}) === 0`
|
||||
}
|
||||
function* FromObject(schema: TObject, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield Policy.IsObjectLike(value)
|
||||
if (IsNumber(schema.minProperties)) yield `Object.getOwnPropertyNames(${value}).length >= ${schema.minProperties}`
|
||||
if (IsNumber(schema.maxProperties)) yield `Object.getOwnPropertyNames(${value}).length <= ${schema.maxProperties}`
|
||||
const knownKeys = Object.getOwnPropertyNames(schema.properties)
|
||||
for (const knownKey of knownKeys) {
|
||||
const memberExpression = MemberExpression.Encode(value, knownKey)
|
||||
const property = schema.properties[knownKey]
|
||||
if (schema.required && schema.required.includes(knownKey)) {
|
||||
yield* Visit(property, references, memberExpression)
|
||||
if (ExtendsUndefinedCheck(property) || IsAnyOrUnknown(property)) yield `('${knownKey}' in ${value})`
|
||||
} else {
|
||||
const expression = CreateExpression(property, references, memberExpression)
|
||||
yield Policy.IsExactOptionalProperty(value, knownKey, expression)
|
||||
}
|
||||
}
|
||||
if (schema.additionalProperties === false) {
|
||||
if (schema.required && schema.required.length === knownKeys.length) {
|
||||
yield `Object.getOwnPropertyNames(${value}).length === ${knownKeys.length}`
|
||||
} else {
|
||||
const keys = `[${knownKeys.map((key) => `'${key}'`).join(', ')}]`
|
||||
yield `Object.getOwnPropertyNames(${value}).every(key => ${keys}.includes(key))`
|
||||
}
|
||||
}
|
||||
if (typeof schema.additionalProperties === 'object') {
|
||||
const expression = CreateExpression(schema.additionalProperties, references, `${value}[key]`)
|
||||
const keys = `[${knownKeys.map((key) => `'${key}'`).join(', ')}]`
|
||||
yield `(Object.getOwnPropertyNames(${value}).every(key => ${keys}.includes(key) || ${expression}))`
|
||||
}
|
||||
}
|
||||
function* FromPromise(schema: TPromise, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `${value} instanceof Promise`
|
||||
}
|
||||
function* FromRecord(schema: TRecord, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield Policy.IsRecordLike(value)
|
||||
if (IsNumber(schema.minProperties)) yield `Object.getOwnPropertyNames(${value}).length >= ${schema.minProperties}`
|
||||
if (IsNumber(schema.maxProperties)) yield `Object.getOwnPropertyNames(${value}).length <= ${schema.maxProperties}`
|
||||
const [patternKey, patternSchema] = Object.entries(schema.patternProperties)[0]
|
||||
const variable = CreateVariable(`${new RegExp(patternKey)}`)
|
||||
const check1 = CreateExpression(patternSchema, references, 'value')
|
||||
const check2 = IsSchema(schema.additionalProperties) ? CreateExpression(schema.additionalProperties, references, value) : schema.additionalProperties === false ? 'false' : 'true'
|
||||
const expression = `(${variable}.test(key) ? ${check1} : ${check2})`
|
||||
yield `(Object.entries(${value}).every(([key, value]) => ${expression}))`
|
||||
}
|
||||
function* FromRef(schema: TRef, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const target = Deref(schema, references)
|
||||
// Reference: If we have seen this reference before we can just yield and return the function call.
|
||||
// If this isn't the case we defer to visit to generate and set the function for subsequent passes.
|
||||
if (state.functions.has(schema.$ref)) return yield `${CreateFunctionName(schema.$ref)}(${value})`
|
||||
yield* Visit(target, references, value)
|
||||
}
|
||||
function* FromRegExp(schema: TRegExp, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const variable = CreateVariable(`${new RegExp(schema.source, schema.flags)};`)
|
||||
yield `(typeof ${value} === 'string')`
|
||||
if (IsNumber(schema.maxLength)) yield `${value}.length <= ${schema.maxLength}`
|
||||
if (IsNumber(schema.minLength)) yield `${value}.length >= ${schema.minLength}`
|
||||
yield `${variable}.test(${value})`
|
||||
}
|
||||
function* FromString(schema: TString, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'string')`
|
||||
if (IsNumber(schema.maxLength)) yield `${value}.length <= ${schema.maxLength}`
|
||||
if (IsNumber(schema.minLength)) yield `${value}.length >= ${schema.minLength}`
|
||||
if (schema.pattern !== undefined) {
|
||||
const variable = CreateVariable(`${new RegExp(schema.pattern)};`)
|
||||
yield `${variable}.test(${value})`
|
||||
}
|
||||
if (schema.format !== undefined) {
|
||||
yield `format('${schema.format}', ${value})`
|
||||
}
|
||||
}
|
||||
function* FromSymbol(schema: TSymbol, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'symbol')`
|
||||
}
|
||||
function* FromTemplateLiteral(schema: TTemplateLiteral, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'string')`
|
||||
const variable = CreateVariable(`${new RegExp(schema.pattern)};`)
|
||||
yield `${variable}.test(${value})`
|
||||
}
|
||||
function* FromThis(schema: TThis, references: TSchema[], value: string): IterableIterator<string> {
|
||||
// Note: This types are assured to be hoisted prior to this call. Just yield the function.
|
||||
yield `${CreateFunctionName(schema.$ref)}(${value})`
|
||||
}
|
||||
function* FromTuple(schema: TTuple, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `Array.isArray(${value})`
|
||||
if (schema.items === undefined) return yield `${value}.length === 0`
|
||||
yield `(${value}.length === ${schema.maxItems})`
|
||||
for (let i = 0; i < schema.items.length; i++) {
|
||||
const expression = CreateExpression(schema.items[i], references, `${value}[${i}]`)
|
||||
yield `${expression}`
|
||||
}
|
||||
}
|
||||
function* FromUndefined(schema: TUndefined, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `${value} === undefined`
|
||||
}
|
||||
function* FromUnion(schema: TUnion, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const expressions = schema.anyOf.map((schema: TSchema) => CreateExpression(schema, references, value))
|
||||
yield `(${expressions.join(' || ')})`
|
||||
}
|
||||
function* FromUint8Array(schema: TUint8Array, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `${value} instanceof Uint8Array`
|
||||
if (IsNumber(schema.maxByteLength)) yield `(${value}.length <= ${schema.maxByteLength})`
|
||||
if (IsNumber(schema.minByteLength)) yield `(${value}.length >= ${schema.minByteLength})`
|
||||
}
|
||||
function* FromUnknown(schema: TUnknown, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield 'true'
|
||||
}
|
||||
function* FromVoid(schema: TVoid, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield Policy.IsVoidLike(value)
|
||||
}
|
||||
function* FromKind(schema: TSchema, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const instance = state.instances.size
|
||||
state.instances.set(instance, schema)
|
||||
yield `kind('${schema[Kind]}', ${instance}, ${value})`
|
||||
}
|
||||
function* Visit(schema: TSchema, references: TSchema[], value: string, useHoisting: boolean = true): IterableIterator<string> {
|
||||
const references_ = IsString(schema.$id) ? [...references, schema] : references
|
||||
const schema_ = schema as any
|
||||
// --------------------------------------------------------------
|
||||
// Hoisting
|
||||
// --------------------------------------------------------------
|
||||
if (useHoisting && IsString(schema.$id)) {
|
||||
const functionName = CreateFunctionName(schema.$id)
|
||||
if (state.functions.has(functionName)) {
|
||||
return yield `${functionName}(${value})`
|
||||
} else {
|
||||
// Note: In the case of cyclic types, we need to create a 'functions' record
|
||||
// to prevent infinitely re-visiting the CreateFunction. Subsequent attempts
|
||||
// to visit will be caught by the above condition.
|
||||
state.functions.set(functionName, '<deferred>')
|
||||
const functionCode = CreateFunction(functionName, schema, references, 'value', false)
|
||||
state.functions.set(functionName, functionCode)
|
||||
return yield `${functionName}(${value})`
|
||||
}
|
||||
}
|
||||
switch (schema_[Kind]) {
|
||||
case 'Any':
|
||||
return yield* FromAny(schema_, references_, value)
|
||||
case 'Argument':
|
||||
return yield* FromArgument(schema_, references_, value)
|
||||
case 'Array':
|
||||
return yield* FromArray(schema_, references_, value)
|
||||
case 'AsyncIterator':
|
||||
return yield* FromAsyncIterator(schema_, references_, value)
|
||||
case 'BigInt':
|
||||
return yield* FromBigInt(schema_, references_, value)
|
||||
case 'Boolean':
|
||||
return yield* FromBoolean(schema_, references_, value)
|
||||
case 'Constructor':
|
||||
return yield* FromConstructor(schema_, references_, value)
|
||||
case 'Date':
|
||||
return yield* FromDate(schema_, references_, value)
|
||||
case 'Function':
|
||||
return yield* FromFunction(schema_, references_, value)
|
||||
case 'Import':
|
||||
return yield* FromImport(schema_, references_, value)
|
||||
case 'Integer':
|
||||
return yield* FromInteger(schema_, references_, value)
|
||||
case 'Intersect':
|
||||
return yield* FromIntersect(schema_, references_, value)
|
||||
case 'Iterator':
|
||||
return yield* FromIterator(schema_, references_, value)
|
||||
case 'Literal':
|
||||
return yield* FromLiteral(schema_, references_, value)
|
||||
case 'Never':
|
||||
return yield* FromNever(schema_, references_, value)
|
||||
case 'Not':
|
||||
return yield* FromNot(schema_, references_, value)
|
||||
case 'Null':
|
||||
return yield* FromNull(schema_, references_, value)
|
||||
case 'Number':
|
||||
return yield* FromNumber(schema_, references_, value)
|
||||
case 'Object':
|
||||
return yield* FromObject(schema_, references_, value)
|
||||
case 'Promise':
|
||||
return yield* FromPromise(schema_, references_, value)
|
||||
case 'Record':
|
||||
return yield* FromRecord(schema_, references_, value)
|
||||
case 'Ref':
|
||||
return yield* FromRef(schema_, references_, value)
|
||||
case 'RegExp':
|
||||
return yield* FromRegExp(schema_, references_, value)
|
||||
case 'String':
|
||||
return yield* FromString(schema_, references_, value)
|
||||
case 'Symbol':
|
||||
return yield* FromSymbol(schema_, references_, value)
|
||||
case 'TemplateLiteral':
|
||||
return yield* FromTemplateLiteral(schema_, references_, value)
|
||||
case 'This':
|
||||
return yield* FromThis(schema_, references_, value)
|
||||
case 'Tuple':
|
||||
return yield* FromTuple(schema_, references_, value)
|
||||
case 'Undefined':
|
||||
return yield* FromUndefined(schema_, references_, value)
|
||||
case 'Union':
|
||||
return yield* FromUnion(schema_, references_, value)
|
||||
case 'Uint8Array':
|
||||
return yield* FromUint8Array(schema_, references_, value)
|
||||
case 'Unknown':
|
||||
return yield* FromUnknown(schema_, references_, value)
|
||||
case 'Void':
|
||||
return yield* FromVoid(schema_, references_, value)
|
||||
default:
|
||||
if (!TypeRegistry.Has(schema_[Kind])) throw new TypeCompilerUnknownTypeError(schema)
|
||||
return yield* FromKind(schema_, references_, value)
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// Compiler State
|
||||
// ----------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
const state = {
|
||||
language: 'javascript', // target language
|
||||
functions: new Map<string, string>(), // local functions
|
||||
variables: new Map<string, string>(), // local variables
|
||||
instances: new Map<number, TSchema>() // exterior kind instances
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// Compiler Factory
|
||||
// ----------------------------------------------------------------
|
||||
function CreateExpression(schema: TSchema, references: TSchema[], value: string, useHoisting: boolean = true): string {
|
||||
return `(${[...Visit(schema, references, value, useHoisting)].join(' && ')})`
|
||||
}
|
||||
function CreateFunctionName($id: string) {
|
||||
return `check_${Identifier.Encode($id)}`
|
||||
}
|
||||
function CreateVariable(expression: string) {
|
||||
const variableName = `local_${state.variables.size}`
|
||||
state.variables.set(variableName, `const ${variableName} = ${expression}`)
|
||||
return variableName
|
||||
}
|
||||
function CreateFunction(name: string, schema: TSchema, references: TSchema[], value: string, useHoisting: boolean = true): string {
|
||||
const [newline, pad] = ['\n', (length: number) => ''.padStart(length, ' ')]
|
||||
const parameter = CreateParameter('value', 'any')
|
||||
const returns = CreateReturns('boolean')
|
||||
const expression = [...Visit(schema, references, value, useHoisting)].map((expression) => `${pad(4)}${expression}`).join(` &&${newline}`)
|
||||
return `function ${name}(${parameter})${returns} {${newline}${pad(2)}return (${newline}${expression}${newline}${pad(2)})\n}`
|
||||
}
|
||||
function CreateParameter(name: string, type: string) {
|
||||
const annotation = state.language === 'typescript' ? `: ${type}` : ''
|
||||
return `${name}${annotation}`
|
||||
}
|
||||
function CreateReturns(type: string) {
|
||||
return state.language === 'typescript' ? `: ${type}` : ''
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// Compile
|
||||
// ----------------------------------------------------------------
|
||||
function Build<T extends TSchema>(schema: T, references: TSchema[], options: TypeCompilerCodegenOptions): string {
|
||||
const functionCode = CreateFunction('check', schema, references, 'value') // will populate functions and variables
|
||||
const parameter = CreateParameter('value', 'any')
|
||||
const returns = CreateReturns('boolean')
|
||||
const functions = [...state.functions.values()]
|
||||
const variables = [...state.variables.values()]
|
||||
// prettier-ignore
|
||||
const checkFunction = IsString(schema.$id) // ensure top level schemas with $id's are hoisted
|
||||
? `return function check(${parameter})${returns} {\n return ${CreateFunctionName(schema.$id)}(value)\n}`
|
||||
: `return ${functionCode}`
|
||||
return [...variables, ...functions, checkFunction].join('\n')
|
||||
}
|
||||
/** Generates the code used to assert this type and returns it as a string */
|
||||
export function Code<T extends TSchema>(schema: T, references: TSchema[], options?: TypeCompilerCodegenOptions): string
|
||||
/** Generates the code used to assert this type and returns it as a string */
|
||||
export function Code<T extends TSchema>(schema: T, options?: TypeCompilerCodegenOptions): string
|
||||
/** Generates the code used to assert this type and returns it as a string */
|
||||
export function Code(...args: any[]) {
|
||||
const defaults = { language: 'javascript' }
|
||||
// prettier-ignore
|
||||
const [schema, references, options] = (
|
||||
args.length === 2 && IsArray(args[1]) ? [args[0], args[1], defaults] :
|
||||
args.length === 2 && !IsArray(args[1]) ? [args[0], [], args[1]] :
|
||||
args.length === 3 ? [args[0], args[1], args[2]] :
|
||||
args.length === 1 ? [args[0], [], defaults] :
|
||||
[null, [], defaults]
|
||||
)
|
||||
// compiler-reset
|
||||
state.language = options.language
|
||||
state.variables.clear()
|
||||
state.functions.clear()
|
||||
state.instances.clear()
|
||||
if (!IsSchema(schema)) throw new TypeCompilerTypeGuardError(schema)
|
||||
for (const schema of references) if (!IsSchema(schema)) throw new TypeCompilerTypeGuardError(schema)
|
||||
return Build(schema, references, options)
|
||||
}
|
||||
/** Compiles a TypeBox type for optimal runtime type checking. Types must be valid TypeBox types of TSchema */
|
||||
export function Compile<T extends TSchema>(schema: T, references: TSchema[] = []): TypeCheck<T> {
|
||||
const generatedCode = Code(schema, references, { language: 'javascript' })
|
||||
const compiledFunction = globalThis.Function('kind', 'format', 'hash', generatedCode)
|
||||
const instances = new Map(state.instances)
|
||||
function typeRegistryFunction(kind: string, instance: number, value: unknown) {
|
||||
if (!TypeRegistry.Has(kind) || !instances.has(instance)) return false
|
||||
const checkFunc = TypeRegistry.Get(kind)!
|
||||
const schema = instances.get(instance)!
|
||||
return checkFunc(schema, value)
|
||||
}
|
||||
function formatRegistryFunction(format: string, value: string) {
|
||||
if (!FormatRegistry.Has(format)) return false
|
||||
const checkFunc = FormatRegistry.Get(format)!
|
||||
return checkFunc(value)
|
||||
}
|
||||
function hashFunction(value: unknown) {
|
||||
return Hash(value)
|
||||
}
|
||||
const checkFunction = compiledFunction(typeRegistryFunction, formatRegistryFunction, hashFunction)
|
||||
return new TypeCheck(schema, references, checkFunction, generatedCode)
|
||||
}
|
||||
}
|
||||
30
src/compiler/index.ts
Normal file
30
src/compiler/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/compiler
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export { ValueError, ValueErrorType, ValueErrorIterator } from '../errors/index'
|
||||
export * from './compiler'
|
||||
639
src/errors/errors.ts
Normal file
639
src/errors/errors.ts
Normal file
@@ -0,0 +1,639 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/errors
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { TypeSystemPolicy } from '../system/index'
|
||||
import { KeyOfPattern } from '../type/keyof/index'
|
||||
import { TypeRegistry, FormatRegistry } from '../type/registry/index'
|
||||
import { ExtendsUndefinedCheck } from '../type/extends/extends-undefined'
|
||||
import { GetErrorFunction } from './function'
|
||||
import { TypeBoxError } from '../type/error/index'
|
||||
import { Deref } from '../value/deref/index'
|
||||
import { Hash } from '../value/hash/index'
|
||||
import { Check } from '../value/check/index'
|
||||
import { Kind } from '../type/symbols/index'
|
||||
|
||||
import type { TSchema } from '../type/schema/index'
|
||||
import type { TAsyncIterator } from '../type/async-iterator/index'
|
||||
import type { TAny } from '../type/any/index'
|
||||
import type { TArray } from '../type/array/index'
|
||||
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 { TFunction } from '../type/function/index'
|
||||
import type { TImport } from '../type/module/index'
|
||||
import type { TInteger } from '../type/integer/index'
|
||||
import type { TIntersect } from '../type/intersect/index'
|
||||
import type { TIterator } from '../type/iterator/index'
|
||||
import type { TLiteral } from '../type/literal/index'
|
||||
import { Never, type TNever } from '../type/never/index'
|
||||
import type { TNot } from '../type/not/index'
|
||||
import type { TNull } from '../type/null/index'
|
||||
import type { TNumber } from '../type/number/index'
|
||||
import type { TObject } from '../type/object/index'
|
||||
import type { TPromise } from '../type/promise/index'
|
||||
import type { TRecord } from '../type/record/index'
|
||||
import type { TRef } from '../type/ref/index'
|
||||
import type { TRegExp } from '../type/regexp/index'
|
||||
import type { TTemplateLiteral } from '../type/template-literal/index'
|
||||
import type { TThis } from '../type/recursive/index'
|
||||
import type { TTuple } from '../type/tuple/index'
|
||||
import type { TUnion } from '../type/union/index'
|
||||
import type { TUnknown } from '../type/unknown/index'
|
||||
import type { TString } from '../type/string/index'
|
||||
import type { TSymbol } from '../type/symbol/index'
|
||||
import type { TUndefined } from '../type/undefined/index'
|
||||
import type { TUint8Array } from '../type/uint8array/index'
|
||||
import type { TVoid } from '../type/void/index'
|
||||
// ------------------------------------------------------------------
|
||||
// ValueGuard
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
import {
|
||||
IsArray,
|
||||
IsUint8Array,
|
||||
IsDate,
|
||||
IsPromise,
|
||||
IsFunction,
|
||||
IsAsyncIterator,
|
||||
IsIterator,
|
||||
IsBoolean,
|
||||
IsNumber,
|
||||
IsBigInt,
|
||||
IsString,
|
||||
IsSymbol,
|
||||
IsInteger,
|
||||
IsNull,
|
||||
IsUndefined
|
||||
} from '../value/guard/index'
|
||||
// ------------------------------------------------------------------
|
||||
// ValueErrorType
|
||||
// ------------------------------------------------------------------
|
||||
export enum ValueErrorType {
|
||||
ArrayContains,
|
||||
ArrayMaxContains,
|
||||
ArrayMaxItems,
|
||||
ArrayMinContains,
|
||||
ArrayMinItems,
|
||||
ArrayUniqueItems,
|
||||
Array,
|
||||
AsyncIterator,
|
||||
BigIntExclusiveMaximum,
|
||||
BigIntExclusiveMinimum,
|
||||
BigIntMaximum,
|
||||
BigIntMinimum,
|
||||
BigIntMultipleOf,
|
||||
BigInt,
|
||||
Boolean,
|
||||
DateExclusiveMaximumTimestamp,
|
||||
DateExclusiveMinimumTimestamp,
|
||||
DateMaximumTimestamp,
|
||||
DateMinimumTimestamp,
|
||||
DateMultipleOfTimestamp,
|
||||
Date,
|
||||
Function,
|
||||
IntegerExclusiveMaximum,
|
||||
IntegerExclusiveMinimum,
|
||||
IntegerMaximum,
|
||||
IntegerMinimum,
|
||||
IntegerMultipleOf,
|
||||
Integer,
|
||||
IntersectUnevaluatedProperties,
|
||||
Intersect,
|
||||
Iterator,
|
||||
Kind,
|
||||
Literal,
|
||||
Never,
|
||||
Not,
|
||||
Null,
|
||||
NumberExclusiveMaximum,
|
||||
NumberExclusiveMinimum,
|
||||
NumberMaximum,
|
||||
NumberMinimum,
|
||||
NumberMultipleOf,
|
||||
Number,
|
||||
ObjectAdditionalProperties,
|
||||
ObjectMaxProperties,
|
||||
ObjectMinProperties,
|
||||
ObjectRequiredProperty,
|
||||
Object,
|
||||
Promise,
|
||||
RegExp,
|
||||
StringFormatUnknown,
|
||||
StringFormat,
|
||||
StringMaxLength,
|
||||
StringMinLength,
|
||||
StringPattern,
|
||||
String,
|
||||
Symbol,
|
||||
TupleLength,
|
||||
Tuple,
|
||||
Uint8ArrayMaxByteLength,
|
||||
Uint8ArrayMinByteLength,
|
||||
Uint8Array,
|
||||
Undefined,
|
||||
Union,
|
||||
Void,
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ValueError
|
||||
// ------------------------------------------------------------------
|
||||
export interface ValueError {
|
||||
type: ValueErrorType
|
||||
schema: TSchema
|
||||
path: string
|
||||
value: unknown
|
||||
message: string
|
||||
errors: ValueErrorIterator[]
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ValueErrors
|
||||
// ------------------------------------------------------------------
|
||||
export class ValueErrorsUnknownTypeError extends TypeBoxError {
|
||||
constructor(public readonly schema: TSchema) {
|
||||
super('Unknown type')
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// EscapeKey
|
||||
// ------------------------------------------------------------------
|
||||
function EscapeKey(key: string): string {
|
||||
return key.replace(/~/g, '~0').replace(/\//g, '~1') // RFC6901 Path
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Guards
|
||||
// ------------------------------------------------------------------
|
||||
function IsDefined<T>(value: unknown): value is T {
|
||||
return value !== undefined
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ValueErrorIterator
|
||||
// ------------------------------------------------------------------
|
||||
export class ValueErrorIterator {
|
||||
constructor(private readonly iterator: IterableIterator<ValueError>) {}
|
||||
public [Symbol.iterator]() {
|
||||
return this.iterator
|
||||
}
|
||||
/** Returns the first value error or undefined if no errors */
|
||||
public First(): ValueError | undefined {
|
||||
const next = this.iterator.next()
|
||||
return next.done ? undefined : next.value
|
||||
}
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// Create
|
||||
// --------------------------------------------------------------------------
|
||||
function Create(errorType: ValueErrorType, schema: TSchema, path: string, value: unknown, errors: ValueErrorIterator[] = []): ValueError {
|
||||
return {
|
||||
type: errorType,
|
||||
schema,
|
||||
path,
|
||||
value,
|
||||
message: GetErrorFunction()({ errorType, path, schema, value, errors }),
|
||||
errors,
|
||||
}
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// Types
|
||||
// --------------------------------------------------------------------------
|
||||
function* FromAny(schema: TAny, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {}
|
||||
function* FromArgument(schema: TAny, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {}
|
||||
function* FromArray(schema: TArray, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsArray(value)) {
|
||||
return yield Create(ValueErrorType.Array, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.minItems) && !(value.length >= schema.minItems)) {
|
||||
yield Create(ValueErrorType.ArrayMinItems, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.maxItems) && !(value.length <= schema.maxItems)) {
|
||||
yield Create(ValueErrorType.ArrayMaxItems, schema, path, value)
|
||||
}
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
yield* Visit(schema.items, references, `${path}/${i}`, value[i])
|
||||
}
|
||||
// prettier-ignore
|
||||
if (schema.uniqueItems === true && !((function () { const set = new Set(); for (const element of value) { const hashed = Hash(element); if (set.has(hashed)) { return false } else { set.add(hashed) } } return true })())) {
|
||||
yield Create(ValueErrorType.ArrayUniqueItems, schema, path, value)
|
||||
}
|
||||
// contains
|
||||
if (!(IsDefined(schema.contains) || IsDefined(schema.minContains) || IsDefined(schema.maxContains))) {
|
||||
return
|
||||
}
|
||||
const containsSchema = IsDefined<TSchema>(schema.contains) ? schema.contains : Never()
|
||||
const containsCount = value.reduce((acc: number, value, index) => (Visit(containsSchema, references, `${path}${index}`, value).next().done === true ? acc + 1 : acc), 0)
|
||||
if (containsCount === 0) {
|
||||
yield Create(ValueErrorType.ArrayContains, schema, path, value)
|
||||
}
|
||||
if (IsNumber(schema.minContains) && containsCount < schema.minContains) {
|
||||
yield Create(ValueErrorType.ArrayMinContains, schema, path, value)
|
||||
}
|
||||
if (IsNumber(schema.maxContains) && containsCount > schema.maxContains) {
|
||||
yield Create(ValueErrorType.ArrayMaxContains, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* FromAsyncIterator(schema: TAsyncIterator, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsAsyncIterator(value)) yield Create(ValueErrorType.AsyncIterator, schema, path, value)
|
||||
}
|
||||
function* FromBigInt(schema: TBigInt, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsBigInt(value)) return yield Create(ValueErrorType.BigInt, schema, path, value)
|
||||
if (IsDefined<bigint>(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) {
|
||||
yield Create(ValueErrorType.BigIntExclusiveMaximum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<bigint>(schema.exclusiveMinimum) && !(value > schema.exclusiveMinimum)) {
|
||||
yield Create(ValueErrorType.BigIntExclusiveMinimum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<bigint>(schema.maximum) && !(value <= schema.maximum)) {
|
||||
yield Create(ValueErrorType.BigIntMaximum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<bigint>(schema.minimum) && !(value >= schema.minimum)) {
|
||||
yield Create(ValueErrorType.BigIntMinimum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<bigint>(schema.multipleOf) && !(value % schema.multipleOf === BigInt(0))) {
|
||||
yield Create(ValueErrorType.BigIntMultipleOf, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* FromBoolean(schema: TBoolean, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsBoolean(value)) yield Create(ValueErrorType.Boolean, schema, path, value)
|
||||
}
|
||||
function* FromConstructor(schema: TConstructor, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
yield* Visit(schema.returns, references, path, value.prototype)
|
||||
}
|
||||
function* FromDate(schema: TDate, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsDate(value)) return yield Create(ValueErrorType.Date, schema, path, value)
|
||||
if (IsDefined<number>(schema.exclusiveMaximumTimestamp) && !(value.getTime() < schema.exclusiveMaximumTimestamp)) {
|
||||
yield Create(ValueErrorType.DateExclusiveMaximumTimestamp, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.exclusiveMinimumTimestamp) && !(value.getTime() > schema.exclusiveMinimumTimestamp)) {
|
||||
yield Create(ValueErrorType.DateExclusiveMinimumTimestamp, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.maximumTimestamp) && !(value.getTime() <= schema.maximumTimestamp)) {
|
||||
yield Create(ValueErrorType.DateMaximumTimestamp, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.minimumTimestamp) && !(value.getTime() >= schema.minimumTimestamp)) {
|
||||
yield Create(ValueErrorType.DateMinimumTimestamp, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.multipleOfTimestamp) && !(value.getTime() % schema.multipleOfTimestamp === 0)) {
|
||||
yield Create(ValueErrorType.DateMultipleOfTimestamp, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* FromFunction(schema: TFunction, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsFunction(value)) yield Create(ValueErrorType.Function, schema, path, value)
|
||||
}
|
||||
function* FromImport(schema: TImport, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
const definitions = globalThis.Object.values(schema.$defs) as TSchema[]
|
||||
const target = schema.$defs[schema.$ref] as TSchema
|
||||
yield* Visit(target, [...references, ...definitions], path, value)
|
||||
}
|
||||
function* FromInteger(schema: TInteger, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsInteger(value)) return yield Create(ValueErrorType.Integer, schema, path, value)
|
||||
if (IsDefined<number>(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) {
|
||||
yield Create(ValueErrorType.IntegerExclusiveMaximum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.exclusiveMinimum) && !(value > schema.exclusiveMinimum)) {
|
||||
yield Create(ValueErrorType.IntegerExclusiveMinimum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.maximum) && !(value <= schema.maximum)) {
|
||||
yield Create(ValueErrorType.IntegerMaximum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.minimum) && !(value >= schema.minimum)) {
|
||||
yield Create(ValueErrorType.IntegerMinimum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.multipleOf) && !(value % schema.multipleOf === 0)) {
|
||||
yield Create(ValueErrorType.IntegerMultipleOf, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* FromIntersect(schema: TIntersect, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
let hasError = false
|
||||
for (const inner of schema.allOf) {
|
||||
for (const error of Visit(inner, references, path, value)) {
|
||||
hasError = true
|
||||
yield error
|
||||
}
|
||||
}
|
||||
if (hasError) {
|
||||
return yield Create(ValueErrorType.Intersect, schema, path, value)
|
||||
}
|
||||
if (schema.unevaluatedProperties === false) {
|
||||
const keyCheck = new RegExp(KeyOfPattern(schema))
|
||||
for (const valueKey of Object.getOwnPropertyNames(value)) {
|
||||
if (!keyCheck.test(valueKey)) {
|
||||
yield Create(ValueErrorType.IntersectUnevaluatedProperties, schema, `${path}/${valueKey}`, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof schema.unevaluatedProperties === 'object') {
|
||||
const keyCheck = new RegExp(KeyOfPattern(schema))
|
||||
for (const valueKey of Object.getOwnPropertyNames(value)) {
|
||||
if (!keyCheck.test(valueKey)) {
|
||||
const next = Visit(schema.unevaluatedProperties, references, `${path}/${valueKey}`, value[valueKey]).next()
|
||||
if (!next.done) yield next.value // yield interior
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function* FromIterator(schema: TIterator, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsIterator(value)) yield Create(ValueErrorType.Iterator, schema, path, value)
|
||||
}
|
||||
function* FromLiteral(schema: TLiteral, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!(value === schema.const)) yield Create(ValueErrorType.Literal, schema, path, value)
|
||||
}
|
||||
function* FromNever(schema: TNever, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
yield Create(ValueErrorType.Never, schema, path, value)
|
||||
}
|
||||
function* FromNot(schema: TNot, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (Visit(schema.not, references, path, value).next().done === true) yield Create(ValueErrorType.Not, schema, path, value)
|
||||
}
|
||||
function* FromNull(schema: TNull, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsNull(value)) yield Create(ValueErrorType.Null, schema, path, value)
|
||||
}
|
||||
function* FromNumber(schema: TNumber, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!TypeSystemPolicy.IsNumberLike(value)) return yield Create(ValueErrorType.Number, schema, path, value)
|
||||
if (IsDefined<number>(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) {
|
||||
yield Create(ValueErrorType.NumberExclusiveMaximum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.exclusiveMinimum) && !(value > schema.exclusiveMinimum)) {
|
||||
yield Create(ValueErrorType.NumberExclusiveMinimum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.maximum) && !(value <= schema.maximum)) {
|
||||
yield Create(ValueErrorType.NumberMaximum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.minimum) && !(value >= schema.minimum)) {
|
||||
yield Create(ValueErrorType.NumberMinimum, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.multipleOf) && !(value % schema.multipleOf === 0)) {
|
||||
yield Create(ValueErrorType.NumberMultipleOf, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* FromObject(schema: TObject, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!TypeSystemPolicy.IsObjectLike(value)) return yield Create(ValueErrorType.Object, schema, path, value)
|
||||
if (IsDefined<number>(schema.minProperties) && !(Object.getOwnPropertyNames(value).length >= schema.minProperties)) {
|
||||
yield Create(ValueErrorType.ObjectMinProperties, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.maxProperties) && !(Object.getOwnPropertyNames(value).length <= schema.maxProperties)) {
|
||||
yield Create(ValueErrorType.ObjectMaxProperties, schema, path, value)
|
||||
}
|
||||
const requiredKeys = Array.isArray(schema.required) ? schema.required : ([] as string[])
|
||||
const knownKeys = Object.getOwnPropertyNames(schema.properties)
|
||||
const unknownKeys = Object.getOwnPropertyNames(value)
|
||||
for (const requiredKey of requiredKeys) {
|
||||
if (unknownKeys.includes(requiredKey)) continue
|
||||
yield Create(ValueErrorType.ObjectRequiredProperty, schema.properties[requiredKey], `${path}/${EscapeKey(requiredKey)}`, undefined)
|
||||
}
|
||||
if (schema.additionalProperties === false) {
|
||||
for (const valueKey of unknownKeys) {
|
||||
if (!knownKeys.includes(valueKey)) {
|
||||
yield Create(ValueErrorType.ObjectAdditionalProperties, schema, `${path}/${EscapeKey(valueKey)}`, value[valueKey])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof schema.additionalProperties === 'object') {
|
||||
for (const valueKey of unknownKeys) {
|
||||
if (knownKeys.includes(valueKey)) continue
|
||||
yield* Visit(schema.additionalProperties as TSchema, references, `${path}/${EscapeKey(valueKey)}`, value[valueKey])
|
||||
}
|
||||
}
|
||||
for (const knownKey of knownKeys) {
|
||||
const property = schema.properties[knownKey]
|
||||
if (schema.required && schema.required.includes(knownKey)) {
|
||||
yield* Visit(property, references, `${path}/${EscapeKey(knownKey)}`, value[knownKey])
|
||||
if (ExtendsUndefinedCheck(schema) && !(knownKey in value)) {
|
||||
yield Create(ValueErrorType.ObjectRequiredProperty, property, `${path}/${EscapeKey(knownKey)}`, undefined)
|
||||
}
|
||||
} else {
|
||||
if (TypeSystemPolicy.IsExactOptionalProperty(value, knownKey)) {
|
||||
yield* Visit(property, references, `${path}/${EscapeKey(knownKey)}`, value[knownKey])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function* FromPromise(schema: TPromise, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsPromise(value)) yield Create(ValueErrorType.Promise, schema, path, value)
|
||||
}
|
||||
function* FromRecord(schema: TRecord, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!TypeSystemPolicy.IsRecordLike(value)) return yield Create(ValueErrorType.Object, schema, path, value)
|
||||
if (IsDefined<number>(schema.minProperties) && !(Object.getOwnPropertyNames(value).length >= schema.minProperties)) {
|
||||
yield Create(ValueErrorType.ObjectMinProperties, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.maxProperties) && !(Object.getOwnPropertyNames(value).length <= schema.maxProperties)) {
|
||||
yield Create(ValueErrorType.ObjectMaxProperties, schema, path, value)
|
||||
}
|
||||
const [patternKey, patternSchema] = Object.entries(schema.patternProperties)[0]
|
||||
const regex = new RegExp(patternKey)
|
||||
for (const [propertyKey, propertyValue] of Object.entries(value)) {
|
||||
if (regex.test(propertyKey)) yield* Visit(patternSchema, references, `${path}/${EscapeKey(propertyKey)}`, propertyValue)
|
||||
}
|
||||
if (typeof schema.additionalProperties === 'object') {
|
||||
for (const [propertyKey, propertyValue] of Object.entries(value)) {
|
||||
if (!regex.test(propertyKey)) yield* Visit(schema.additionalProperties as TSchema, references, `${path}/${EscapeKey(propertyKey)}`, propertyValue)
|
||||
}
|
||||
}
|
||||
if (schema.additionalProperties === false) {
|
||||
for (const [propertyKey, propertyValue] of Object.entries(value)) {
|
||||
if (regex.test(propertyKey)) continue
|
||||
return yield Create(ValueErrorType.ObjectAdditionalProperties, schema, `${path}/${EscapeKey(propertyKey)}`, propertyValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
function* FromRef(schema: TRef, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
yield* Visit(Deref(schema, references), references, path, value)
|
||||
}
|
||||
function* FromRegExp(schema: TRegExp, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsString(value)) return yield Create(ValueErrorType.String, schema, path, value)
|
||||
if (IsDefined<number>(schema.minLength) && !(value.length >= schema.minLength)) {
|
||||
yield Create(ValueErrorType.StringMinLength, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.maxLength) && !(value.length <= schema.maxLength)) {
|
||||
yield Create(ValueErrorType.StringMaxLength, schema, path, value)
|
||||
}
|
||||
const regex = new RegExp(schema.source, schema.flags)
|
||||
if (!regex.test(value)) {
|
||||
return yield Create(ValueErrorType.RegExp, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* FromString(schema: TString, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsString(value)) return yield Create(ValueErrorType.String, schema, path, value)
|
||||
if (IsDefined<number>(schema.minLength) && !(value.length >= schema.minLength)) {
|
||||
yield Create(ValueErrorType.StringMinLength, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.maxLength) && !(value.length <= schema.maxLength)) {
|
||||
yield Create(ValueErrorType.StringMaxLength, schema, path, value)
|
||||
}
|
||||
if (IsString(schema.pattern)) {
|
||||
const regex = new RegExp(schema.pattern)
|
||||
if (!regex.test(value)) {
|
||||
yield Create(ValueErrorType.StringPattern, schema, path, value)
|
||||
}
|
||||
}
|
||||
if (IsString(schema.format)) {
|
||||
if (!FormatRegistry.Has(schema.format)) {
|
||||
yield Create(ValueErrorType.StringFormatUnknown, schema, path, value)
|
||||
} else {
|
||||
const format = FormatRegistry.Get(schema.format)!
|
||||
if (!format(value)) {
|
||||
yield Create(ValueErrorType.StringFormat, schema, path, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function* FromSymbol(schema: TSymbol, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsSymbol(value)) yield Create(ValueErrorType.Symbol, schema, path, value)
|
||||
}
|
||||
function* FromTemplateLiteral(schema: TTemplateLiteral, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsString(value)) return yield Create(ValueErrorType.String, schema, path, value)
|
||||
const regex = new RegExp(schema.pattern)
|
||||
if (!regex.test(value)) {
|
||||
yield Create(ValueErrorType.StringPattern, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* FromThis(schema: TThis, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
yield* Visit(Deref(schema, references), references, path, value)
|
||||
}
|
||||
function* FromTuple(schema: TTuple<any[]>, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsArray(value)) return yield Create(ValueErrorType.Tuple, schema, path, value)
|
||||
if (schema.items === undefined && !(value.length === 0)) {
|
||||
return yield Create(ValueErrorType.TupleLength, schema, path, value)
|
||||
}
|
||||
if (!(value.length === schema.maxItems)) {
|
||||
return yield Create(ValueErrorType.TupleLength, schema, path, value)
|
||||
}
|
||||
if (!schema.items) {
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < schema.items.length; i++) {
|
||||
yield* Visit(schema.items[i], references, `${path}/${i}`, value[i])
|
||||
}
|
||||
}
|
||||
function* FromUndefined(schema: TUndefined, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsUndefined(value)) yield Create(ValueErrorType.Undefined, schema, path, value)
|
||||
}
|
||||
function* FromUnion(schema: TUnion, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (Check(schema, references, value)) return
|
||||
const errors = schema.anyOf.map((variant) => new ValueErrorIterator(Visit(variant, references, path, value)))
|
||||
yield Create(ValueErrorType.Union, schema, path, value, errors)
|
||||
}
|
||||
function* FromUint8Array(schema: TUint8Array, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsUint8Array(value)) return yield Create(ValueErrorType.Uint8Array, schema, path, value)
|
||||
if (IsDefined<number>(schema.maxByteLength) && !(value.length <= schema.maxByteLength)) {
|
||||
yield Create(ValueErrorType.Uint8ArrayMaxByteLength, schema, path, value)
|
||||
}
|
||||
if (IsDefined<number>(schema.minByteLength) && !(value.length >= schema.minByteLength)) {
|
||||
yield Create(ValueErrorType.Uint8ArrayMinByteLength, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* FromUnknown(schema: TUnknown, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {}
|
||||
function* FromVoid(schema: TVoid, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!TypeSystemPolicy.IsVoidLike(value)) yield Create(ValueErrorType.Void, schema, path, value)
|
||||
}
|
||||
function* FromKind(schema: TSchema, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
const check = TypeRegistry.Get(schema[Kind])!
|
||||
if (!check(schema, value)) yield Create(ValueErrorType.Kind, schema, path, value)
|
||||
}
|
||||
function* Visit<T extends TSchema>(schema: T, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
const references_ = IsDefined<string>(schema.$id) ? [...references, schema] : references
|
||||
const schema_ = schema as any
|
||||
switch (schema_[Kind]) {
|
||||
case 'Any':
|
||||
return yield* FromAny(schema_, references_, path, value)
|
||||
case 'Argument':
|
||||
return yield* FromArgument(schema_, references_, path, value)
|
||||
case 'Array':
|
||||
return yield* FromArray(schema_, references_, path, value)
|
||||
case 'AsyncIterator':
|
||||
return yield* FromAsyncIterator(schema_, references_, path, value)
|
||||
case 'BigInt':
|
||||
return yield* FromBigInt(schema_, references_, path, value)
|
||||
case 'Boolean':
|
||||
return yield* FromBoolean(schema_, references_, path, value)
|
||||
case 'Constructor':
|
||||
return yield* FromConstructor(schema_, references_, path, value)
|
||||
case 'Date':
|
||||
return yield* FromDate(schema_, references_, path, value)
|
||||
case 'Function':
|
||||
return yield* FromFunction(schema_, references_, path, value)
|
||||
case 'Import':
|
||||
return yield* FromImport(schema_, references_, path, value)
|
||||
case 'Integer':
|
||||
return yield* FromInteger(schema_, references_, path, value)
|
||||
case 'Intersect':
|
||||
return yield* FromIntersect(schema_, references_, path, value)
|
||||
case 'Iterator':
|
||||
return yield* FromIterator(schema_, references_, path, value)
|
||||
case 'Literal':
|
||||
return yield* FromLiteral(schema_, references_, path, value)
|
||||
case 'Never':
|
||||
return yield* FromNever(schema_, references_, path, value)
|
||||
case 'Not':
|
||||
return yield* FromNot(schema_, references_, path, value)
|
||||
case 'Null':
|
||||
return yield* FromNull(schema_, references_, path, value)
|
||||
case 'Number':
|
||||
return yield* FromNumber(schema_, references_, path, value)
|
||||
case 'Object':
|
||||
return yield* FromObject(schema_, references_, path, value)
|
||||
case 'Promise':
|
||||
return yield* FromPromise(schema_, references_, path, value)
|
||||
case 'Record':
|
||||
return yield* FromRecord(schema_, references_, path, value)
|
||||
case 'Ref':
|
||||
return yield* FromRef(schema_, references_, path, value)
|
||||
case 'RegExp':
|
||||
return yield* FromRegExp(schema_, references_, path, value)
|
||||
case 'String':
|
||||
return yield* FromString(schema_, references_, path, value)
|
||||
case 'Symbol':
|
||||
return yield* FromSymbol(schema_, references_, path, value)
|
||||
case 'TemplateLiteral':
|
||||
return yield* FromTemplateLiteral(schema_, references_, path, value)
|
||||
case 'This':
|
||||
return yield* FromThis(schema_, references_, path, value)
|
||||
case 'Tuple':
|
||||
return yield* FromTuple(schema_, references_, path, value)
|
||||
case 'Undefined':
|
||||
return yield* FromUndefined(schema_, references_, path, value)
|
||||
case 'Union':
|
||||
return yield* FromUnion(schema_, references_, path, value)
|
||||
case 'Uint8Array':
|
||||
return yield* FromUint8Array(schema_, references_, path, value)
|
||||
case 'Unknown':
|
||||
return yield* FromUnknown(schema_, references_, path, value)
|
||||
case 'Void':
|
||||
return yield* FromVoid(schema_, references_, path, value)
|
||||
default:
|
||||
if (!TypeRegistry.Has(schema_[Kind])) throw new ValueErrorsUnknownTypeError(schema)
|
||||
return yield* FromKind(schema_, references_, path, value)
|
||||
}
|
||||
}
|
||||
/** Returns an iterator for each error in this value. */
|
||||
export function Errors<T extends TSchema>(schema: T, references: TSchema[], value: unknown): ValueErrorIterator
|
||||
/** Returns an iterator for each error in this value. */
|
||||
export function Errors<T extends TSchema>(schema: T, value: unknown): ValueErrorIterator
|
||||
/** Returns an iterator for each error in this value. */
|
||||
export function Errors(...args: any[]) {
|
||||
const iterator = args.length === 3 ? Visit(args[0], args[1], '', args[2]) : Visit(args[0], [], '', args[1])
|
||||
return new ValueErrorIterator(iterator)
|
||||
}
|
||||
195
src/errors/function.ts
Normal file
195
src/errors/function.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/system
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { TSchema } from '../type/schema/index'
|
||||
import { Kind } from '../type/symbols/index'
|
||||
import { ValueErrorIterator, ValueErrorType } from './errors'
|
||||
|
||||
/** Creates an error message using en-US as the default locale */
|
||||
export function DefaultErrorFunction(error: ErrorFunctionParameter) {
|
||||
switch (error.errorType) {
|
||||
case ValueErrorType.ArrayContains:
|
||||
return 'Expected array to contain at least one matching value'
|
||||
case ValueErrorType.ArrayMaxContains:
|
||||
return `Expected array to contain no more than ${error.schema.maxContains} matching values`
|
||||
case ValueErrorType.ArrayMinContains:
|
||||
return `Expected array to contain at least ${error.schema.minContains} matching values`
|
||||
case ValueErrorType.ArrayMaxItems:
|
||||
return `Expected array length to be less or equal to ${error.schema.maxItems}`
|
||||
case ValueErrorType.ArrayMinItems:
|
||||
return `Expected array length to be greater or equal to ${error.schema.minItems}`
|
||||
case ValueErrorType.ArrayUniqueItems:
|
||||
return 'Expected array elements to be unique'
|
||||
case ValueErrorType.Array:
|
||||
return 'Expected array'
|
||||
case ValueErrorType.AsyncIterator:
|
||||
return 'Expected AsyncIterator'
|
||||
case ValueErrorType.BigIntExclusiveMaximum:
|
||||
return `Expected bigint to be less than ${error.schema.exclusiveMaximum}`
|
||||
case ValueErrorType.BigIntExclusiveMinimum:
|
||||
return `Expected bigint to be greater than ${error.schema.exclusiveMinimum}`
|
||||
case ValueErrorType.BigIntMaximum:
|
||||
return `Expected bigint to be less or equal to ${error.schema.maximum}`
|
||||
case ValueErrorType.BigIntMinimum:
|
||||
return `Expected bigint to be greater or equal to ${error.schema.minimum}`
|
||||
case ValueErrorType.BigIntMultipleOf:
|
||||
return `Expected bigint to be a multiple of ${error.schema.multipleOf}`
|
||||
case ValueErrorType.BigInt:
|
||||
return 'Expected bigint'
|
||||
case ValueErrorType.Boolean:
|
||||
return 'Expected boolean'
|
||||
case ValueErrorType.DateExclusiveMinimumTimestamp:
|
||||
return `Expected Date timestamp to be greater than ${error.schema.exclusiveMinimumTimestamp}`
|
||||
case ValueErrorType.DateExclusiveMaximumTimestamp:
|
||||
return `Expected Date timestamp to be less than ${error.schema.exclusiveMaximumTimestamp}`
|
||||
case ValueErrorType.DateMinimumTimestamp:
|
||||
return `Expected Date timestamp to be greater or equal to ${error.schema.minimumTimestamp}`
|
||||
case ValueErrorType.DateMaximumTimestamp:
|
||||
return `Expected Date timestamp to be less or equal to ${error.schema.maximumTimestamp}`
|
||||
case ValueErrorType.DateMultipleOfTimestamp:
|
||||
return `Expected Date timestamp to be a multiple of ${error.schema.multipleOfTimestamp}`
|
||||
case ValueErrorType.Date:
|
||||
return 'Expected Date'
|
||||
case ValueErrorType.Function:
|
||||
return 'Expected function'
|
||||
case ValueErrorType.IntegerExclusiveMaximum:
|
||||
return `Expected integer to be less than ${error.schema.exclusiveMaximum}`
|
||||
case ValueErrorType.IntegerExclusiveMinimum:
|
||||
return `Expected integer to be greater than ${error.schema.exclusiveMinimum}`
|
||||
case ValueErrorType.IntegerMaximum:
|
||||
return `Expected integer to be less or equal to ${error.schema.maximum}`
|
||||
case ValueErrorType.IntegerMinimum:
|
||||
return `Expected integer to be greater or equal to ${error.schema.minimum}`
|
||||
case ValueErrorType.IntegerMultipleOf:
|
||||
return `Expected integer to be a multiple of ${error.schema.multipleOf}`
|
||||
case ValueErrorType.Integer:
|
||||
return 'Expected integer'
|
||||
case ValueErrorType.IntersectUnevaluatedProperties:
|
||||
return 'Unexpected property'
|
||||
case ValueErrorType.Intersect:
|
||||
return 'Expected all values to match'
|
||||
case ValueErrorType.Iterator:
|
||||
return 'Expected Iterator'
|
||||
case ValueErrorType.Literal:
|
||||
return `Expected ${typeof error.schema.const === 'string' ? `'${error.schema.const}'` : error.schema.const}`
|
||||
case ValueErrorType.Never:
|
||||
return 'Never'
|
||||
case ValueErrorType.Not:
|
||||
return 'Value should not match'
|
||||
case ValueErrorType.Null:
|
||||
return 'Expected null'
|
||||
case ValueErrorType.NumberExclusiveMaximum:
|
||||
return `Expected number to be less than ${error.schema.exclusiveMaximum}`
|
||||
case ValueErrorType.NumberExclusiveMinimum:
|
||||
return `Expected number to be greater than ${error.schema.exclusiveMinimum}`
|
||||
case ValueErrorType.NumberMaximum:
|
||||
return `Expected number to be less or equal to ${error.schema.maximum}`
|
||||
case ValueErrorType.NumberMinimum:
|
||||
return `Expected number to be greater or equal to ${error.schema.minimum}`
|
||||
case ValueErrorType.NumberMultipleOf:
|
||||
return `Expected number to be a multiple of ${error.schema.multipleOf}`
|
||||
case ValueErrorType.Number:
|
||||
return 'Expected number'
|
||||
case ValueErrorType.Object:
|
||||
return 'Expected object'
|
||||
case ValueErrorType.ObjectAdditionalProperties:
|
||||
return 'Unexpected property'
|
||||
case ValueErrorType.ObjectMaxProperties:
|
||||
return `Expected object to have no more than ${error.schema.maxProperties} properties`
|
||||
case ValueErrorType.ObjectMinProperties:
|
||||
return `Expected object to have at least ${error.schema.minProperties} properties`
|
||||
case ValueErrorType.ObjectRequiredProperty:
|
||||
return 'Expected required property'
|
||||
case ValueErrorType.Promise:
|
||||
return 'Expected Promise'
|
||||
case ValueErrorType.RegExp:
|
||||
return 'Expected string to match regular expression'
|
||||
case ValueErrorType.StringFormatUnknown:
|
||||
return `Unknown format '${error.schema.format}'`
|
||||
case ValueErrorType.StringFormat:
|
||||
return `Expected string to match '${error.schema.format}' format`
|
||||
case ValueErrorType.StringMaxLength:
|
||||
return `Expected string length less or equal to ${error.schema.maxLength}`
|
||||
case ValueErrorType.StringMinLength:
|
||||
return `Expected string length greater or equal to ${error.schema.minLength}`
|
||||
case ValueErrorType.StringPattern:
|
||||
return `Expected string to match '${error.schema.pattern}'`
|
||||
case ValueErrorType.String:
|
||||
return 'Expected string'
|
||||
case ValueErrorType.Symbol:
|
||||
return 'Expected symbol'
|
||||
case ValueErrorType.TupleLength:
|
||||
return `Expected tuple to have ${error.schema.maxItems || 0} elements`
|
||||
case ValueErrorType.Tuple:
|
||||
return 'Expected tuple'
|
||||
case ValueErrorType.Uint8ArrayMaxByteLength:
|
||||
return `Expected byte length less or equal to ${error.schema.maxByteLength}`
|
||||
case ValueErrorType.Uint8ArrayMinByteLength:
|
||||
return `Expected byte length greater or equal to ${error.schema.minByteLength}`
|
||||
case ValueErrorType.Uint8Array:
|
||||
return 'Expected Uint8Array'
|
||||
case ValueErrorType.Undefined:
|
||||
return 'Expected undefined'
|
||||
case ValueErrorType.Union:
|
||||
return 'Expected union value'
|
||||
case ValueErrorType.Void:
|
||||
return 'Expected void'
|
||||
case ValueErrorType.Kind:
|
||||
return `Expected kind '${error.schema[Kind]}'`
|
||||
default:
|
||||
return 'Unknown error type'
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ErrorFunction
|
||||
// ------------------------------------------------------------------
|
||||
export type ErrorFunctionParameter = {
|
||||
/** The type of validation error */
|
||||
errorType: ValueErrorType
|
||||
/** The path of the error */
|
||||
path: string
|
||||
/** The schema associated with the error */
|
||||
schema: TSchema
|
||||
/** The value associated with the error */
|
||||
value: unknown
|
||||
/** Interior errors for this error */
|
||||
errors: ValueErrorIterator[]
|
||||
}
|
||||
export type ErrorFunction = (parameter: ErrorFunctionParameter) => string
|
||||
/** Manages error message providers */
|
||||
let errorFunction: ErrorFunction = DefaultErrorFunction
|
||||
|
||||
/** Sets the error function used to generate error messages. */
|
||||
export function SetErrorFunction(callback: ErrorFunction) {
|
||||
errorFunction = callback
|
||||
}
|
||||
/** Gets the error function used to generate error messages */
|
||||
export function GetErrorFunction(): ErrorFunction {
|
||||
return errorFunction
|
||||
}
|
||||
30
src/errors/index.ts
Normal file
30
src/errors/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/errors
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './errors'
|
||||
export * from './function'
|
||||
109
src/index.ts
Normal file
109
src/index.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Infrastructure
|
||||
// ------------------------------------------------------------------
|
||||
export * from './type/clone/index'
|
||||
export * from './type/create/index'
|
||||
export * from './type/error/index'
|
||||
export * from './type/guard/index'
|
||||
export * from './type/helpers/index'
|
||||
export * from './type/patterns/index'
|
||||
export * from './type/registry/index'
|
||||
export * from './type/sets/index'
|
||||
export * from './type/symbols/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Types
|
||||
// ------------------------------------------------------------------
|
||||
export * from './type/any/index'
|
||||
export * from './type/array/index'
|
||||
export * from './type/argument/index'
|
||||
export * from './type/async-iterator/index'
|
||||
export * from './type/awaited/index'
|
||||
export * from './type/bigint/index'
|
||||
export * from './type/boolean/index'
|
||||
export * from './type/composite/index'
|
||||
export * from './type/const/index'
|
||||
export * from './type/constructor/index'
|
||||
export * from './type/constructor-parameters/index'
|
||||
export * from './type/date/index'
|
||||
export * from './type/enum/index'
|
||||
export * from './type/exclude/index'
|
||||
export * from './type/extends/index'
|
||||
export * from './type/extract/index'
|
||||
export * from './type/function/index'
|
||||
export * from './type/indexed/index'
|
||||
export * from './type/instance-type/index'
|
||||
export * from './type/instantiate/index'
|
||||
export * from './type/integer/index'
|
||||
export * from './type/intersect/index'
|
||||
export * from './type/iterator/index'
|
||||
export * from './type/intrinsic/index'
|
||||
export * from './type/keyof/index'
|
||||
export * from './type/literal/index'
|
||||
export * from './type/module/index'
|
||||
export * from './type/mapped/index'
|
||||
export * from './type/never/index'
|
||||
export * from './type/not/index'
|
||||
export * from './type/null/index'
|
||||
export * from './type/number/index'
|
||||
export * from './type/object/index'
|
||||
export * from './type/omit/index'
|
||||
export * from './type/optional/index'
|
||||
export * from './type/parameters/index'
|
||||
export * from './type/partial/index'
|
||||
export * from './type/pick/index'
|
||||
export * from './type/promise/index'
|
||||
export * from './type/readonly/index'
|
||||
export * from './type/readonly-optional/index'
|
||||
export * from './type/record/index'
|
||||
export * from './type/recursive/index'
|
||||
export * from './type/ref/index'
|
||||
export * from './type/regexp/index'
|
||||
export * from './type/required/index'
|
||||
export * from './type/rest/index'
|
||||
export * from './type/return-type/index'
|
||||
export * from './type/schema/index'
|
||||
export * from './type/static/index'
|
||||
export * from './type/string/index'
|
||||
export * from './type/symbol/index'
|
||||
export * from './type/template-literal/index'
|
||||
export * from './type/transform/index'
|
||||
export * from './type/tuple/index'
|
||||
export * from './type/uint8array/index'
|
||||
export * from './type/undefined/index'
|
||||
export * from './type/union/index'
|
||||
export * from './type/unknown/index'
|
||||
export * from './type/unsafe/index'
|
||||
export * from './type/void/index'
|
||||
// ------------------------------------------------------------------
|
||||
// Type.*
|
||||
// ------------------------------------------------------------------
|
||||
export * from './type/type/index'
|
||||
30
src/parser/index.ts
Normal file
30
src/parser/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * as Runtime from './runtime/index'
|
||||
export * as Static from './static/index'
|
||||
104
src/parser/runtime/guard.ts
Normal file
104
src/parser/runtime/guard.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { IArray, IConst, IContext, IIdent, INumber, IOptional, IRef, IString, ITuple, IUnion } from './types'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Value Guard
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function HasPropertyKey<Key extends PropertyKey>(value: Record<PropertyKey, unknown>, key: Key): value is Record<PropertyKey, unknown> & { [_ in Key]: unknown } {
|
||||
return key in value
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectValue(value: unknown): value is Record<PropertyKey, unknown> {
|
||||
return typeof value === 'object' && value !== null
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsArrayValue(value: unknown): value is unknown[] {
|
||||
return globalThis.Array.isArray(value)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Parser Guard
|
||||
// ------------------------------------------------------------------
|
||||
/** Returns true if the value is a Array Parser */
|
||||
export function IsArray(value: unknown): value is IArray {
|
||||
return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Array' && HasPropertyKey(value, 'parser') && IsObjectValue(value.parser)
|
||||
}
|
||||
/** Returns true if the value is a Const Parser */
|
||||
export function IsConst(value: unknown): value is IConst {
|
||||
return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Const' && HasPropertyKey(value, 'value') && typeof value.value === 'string'
|
||||
}
|
||||
/** Returns true if the value is a Context Parser */
|
||||
export function IsContext(value: unknown): value is IContext {
|
||||
return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Context' && HasPropertyKey(value, 'left') && IsParser(value.left) && HasPropertyKey(value, 'right') && IsParser(value.right)
|
||||
}
|
||||
/** Returns true if the value is a Ident Parser */
|
||||
export function IsIdent(value: unknown): value is IIdent {
|
||||
return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Ident'
|
||||
}
|
||||
/** Returns true if the value is a Number Parser */
|
||||
export function IsNumber(value: unknown): value is INumber {
|
||||
return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Number'
|
||||
}
|
||||
/** Returns true if the value is a Optional Parser */
|
||||
export function IsOptional(value: unknown): value is IOptional {
|
||||
return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Optional' && HasPropertyKey(value, 'parser') && IsObjectValue(value.parser)
|
||||
}
|
||||
/** Returns true if the value is a Ref Parser */
|
||||
export function IsRef(value: unknown): value is IRef {
|
||||
return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Ref' && HasPropertyKey(value, 'ref') && typeof value.ref === 'string'
|
||||
}
|
||||
/** Returns true if the value is a String Parser */
|
||||
export function IsString(value: unknown): value is IString {
|
||||
return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'String' && HasPropertyKey(value, 'options') && IsArrayValue(value.options)
|
||||
}
|
||||
/** Returns true if the value is a Tuple Parser */
|
||||
export function IsTuple(value: unknown): value is ITuple {
|
||||
return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Tuple' && HasPropertyKey(value, 'parsers') && IsArrayValue(value.parsers)
|
||||
}
|
||||
/** Returns true if the value is a Union Parser */
|
||||
export function IsUnion(value: unknown): value is IUnion {
|
||||
return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Union' && HasPropertyKey(value, 'parsers') && IsArrayValue(value.parsers)
|
||||
}
|
||||
/** Returns true if the value is a Parser */
|
||||
export function IsParser(value: unknown) {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsArray(value) ||
|
||||
IsConst(value) ||
|
||||
IsContext(value) ||
|
||||
IsIdent(value) ||
|
||||
IsNumber(value) ||
|
||||
IsOptional(value) ||
|
||||
IsRef(value) ||
|
||||
IsString(value) ||
|
||||
IsTuple(value) ||
|
||||
IsUnion(value)
|
||||
)
|
||||
}
|
||||
33
src/parser/runtime/index.ts
Normal file
33
src/parser/runtime/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * as Guard from './guard'
|
||||
export * as Token from './token'
|
||||
export * from './types'
|
||||
export * from './module'
|
||||
export * from './parse'
|
||||
52
src/parser/runtime/module.ts
Normal file
52
src/parser/runtime/module.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import * as Types from './types'
|
||||
import { Parse } from './parse'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Module
|
||||
// ------------------------------------------------------------------
|
||||
export class Module<Properties extends Types.IModuleProperties = Types.IModuleProperties> {
|
||||
constructor(private readonly properties: Properties) {}
|
||||
|
||||
/** Parses using one of the parsers defined on this instance */
|
||||
public Parse<Key extends keyof Properties>(key: Key, content: string, context: unknown): [] | [Types.StaticParser<Properties[Key]>, string]
|
||||
/** Parses using one of the parsers defined on this instance */
|
||||
public Parse<Key extends keyof Properties>(key: Key, content: string): [] | [Types.StaticParser<Properties[Key]>, string]
|
||||
/** Parses using one of the parsers defined on this instance */
|
||||
public Parse(...args: any[]): never {
|
||||
// prettier-ignore
|
||||
const [key, content, context] = (
|
||||
args.length === 3 ? [args[0], args[1], args[2]] :
|
||||
args.length === 2 ? [args[0], args[1], undefined] :
|
||||
(() => { throw Error('Invalid parse arguments') })()
|
||||
)
|
||||
return Parse(this.properties, this.properties[key], content, context) as never
|
||||
}
|
||||
}
|
||||
179
src/parser/runtime/parse.ts
Normal file
179
src/parser/runtime/parse.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import * as Guard from './guard'
|
||||
import * as Token from './token'
|
||||
import * as Types from './types'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Context
|
||||
// ------------------------------------------------------------------
|
||||
function ParseContext<ModuleProperties extends Types.IModuleProperties, Parser extends Types.IParser>(moduleProperties: ModuleProperties, left: Parser, right: Parser, code: string, context: unknown): unknown[] {
|
||||
const result = ParseParser(moduleProperties, left, code, context)
|
||||
return result.length === 2 ? ParseParser(moduleProperties, right, result[1], result[0]) : []
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Array
|
||||
// ------------------------------------------------------------------
|
||||
function ParseArray<ModuleProperties extends Types.IModuleProperties, Parser extends Types.IParser>(moduleProperties: ModuleProperties, parser: Parser, code: string, context: unknown): unknown[] {
|
||||
const buffer = [] as unknown[]
|
||||
let rest = code
|
||||
while (rest.length > 0) {
|
||||
const result = ParseParser(moduleProperties, parser, rest, context)
|
||||
if (result.length === 0) return [buffer, rest]
|
||||
buffer.push(result[0])
|
||||
rest = result[1]
|
||||
}
|
||||
return [buffer, rest]
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Const
|
||||
// ------------------------------------------------------------------
|
||||
function ParseConst<Value extends string>(value: Value, code: string, context: unknown): [] | [Value, string] {
|
||||
return Token.Const(value, code) as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Ident
|
||||
// ------------------------------------------------------------------
|
||||
function ParseIdent(code: string, _context: unknown): [] | [string, string] {
|
||||
return Token.Ident(code)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Number
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function ParseNumber(code: string, _context: unknown): [] | [string, string] {
|
||||
return Token.Number(code)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Optional
|
||||
// ------------------------------------------------------------------
|
||||
function ParseOptional<ModuleProperties extends Types.IModuleProperties, Parser extends Types.IParser>(moduleProperties: ModuleProperties, parser: Parser, code: string, context: unknown): [] | [[unknown] | [], unknown] {
|
||||
const result = ParseParser(moduleProperties, parser, code, context)
|
||||
return (result.length === 2 ? [[result[0]], result[1]] : [[], code]) as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Ref
|
||||
// ------------------------------------------------------------------
|
||||
function ParseRef<ModuleProperties extends Types.IModuleProperties, Ref extends string>(moduleProperties: ModuleProperties, ref: Ref, code: string, context: unknown): [] | [string, string] {
|
||||
const parser = moduleProperties[ref]
|
||||
if (!Guard.IsParser(parser)) throw Error(`Cannot dereference Parser '${ref}'`)
|
||||
return ParseParser(moduleProperties, parser, code, context) as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// String
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function ParseString(options: string[], code: string, _context: unknown): [] | [string, string] {
|
||||
return Token.String(options, code)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Tuple
|
||||
// ------------------------------------------------------------------
|
||||
function ParseTuple<ModuleProperties extends Types.IModuleProperties, Parsers extends Types.IParser[]>(moduleProperties: ModuleProperties, parsers: [...Parsers], code: string, context: unknown): [] | [unknown[], string] {
|
||||
const buffer = [] as unknown[]
|
||||
let rest = code
|
||||
for (const parser of parsers) {
|
||||
const result = ParseParser(moduleProperties, parser, rest, context)
|
||||
if (result.length === 0) return []
|
||||
buffer.push(result[0])
|
||||
rest = result[1]
|
||||
}
|
||||
return [buffer, rest]
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Union
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function ParseUnion<ModuleProperties extends Types.IModuleProperties, Parsers extends Types.IParser[]>(moduleProperties: ModuleProperties, parsers: [...Parsers], code: string, context: unknown): [] | [unknown, string] {
|
||||
for(const parser of parsers) {
|
||||
const result = ParseParser(moduleProperties, parser, code, context)
|
||||
if(result.length === 0) continue
|
||||
return result
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Parser
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function ParseParser<Parser extends Types.IParser>(moduleProperties: Types.IModuleProperties, parser: Parser, code: string, context: unknown): [] | [Types.StaticParser<Parser>, string] {
|
||||
const result = (
|
||||
Guard.IsContext(parser) ? ParseContext(moduleProperties, parser.left, parser.right, code, context) :
|
||||
Guard.IsArray(parser) ? ParseArray(moduleProperties, parser.parser, code, context) :
|
||||
Guard.IsConst(parser) ? ParseConst(parser.value, code, context) :
|
||||
Guard.IsIdent(parser) ? ParseIdent(code, context) :
|
||||
Guard.IsNumber(parser) ? ParseNumber(code, context) :
|
||||
Guard.IsOptional(parser) ? ParseOptional(moduleProperties, parser.parser, code, context) :
|
||||
Guard.IsRef(parser) ? ParseRef(moduleProperties, parser.ref, code, context) :
|
||||
Guard.IsString(parser) ? ParseString(parser.options, code, context) :
|
||||
Guard.IsTuple(parser) ? ParseTuple(moduleProperties, parser.parsers, code, context) :
|
||||
Guard.IsUnion(parser) ? ParseUnion(moduleProperties, parser.parsers, code, context) :
|
||||
[]
|
||||
)
|
||||
return (
|
||||
result.length === 2
|
||||
? [parser.mapping(result[0], context), result[1]]
|
||||
: result
|
||||
) as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Parse
|
||||
// ------------------------------------------------------------------
|
||||
/** Parses content using the given Parser */
|
||||
// prettier-ignore
|
||||
export function Parse<Parser extends Types.IParser>(moduleProperties: Types.IModuleProperties, parser: Parser, code: string, context: unknown): [] | [Types.StaticParser<Parser>, string]
|
||||
/** Parses content using the given Parser */
|
||||
// prettier-ignore
|
||||
export function Parse<Parser extends Types.IParser>(moduleProperties: Types.IModuleProperties, parser: Parser, code: string): [] | [Types.StaticParser<Parser>, string]
|
||||
/** Parses content using the given Parser */
|
||||
// prettier-ignore
|
||||
export function Parse<Parser extends Types.IParser>(parser: Parser, content: string, context: unknown): [] | [Types.StaticParser<Parser>, string]
|
||||
/** Parses content using the given Parser */
|
||||
// prettier-ignore
|
||||
export function Parse<Parser extends Types.IParser>(parser: Parser, content: string): [] | [Types.StaticParser<Parser>, string]
|
||||
/** Parses content using the given parser */
|
||||
// prettier-ignore
|
||||
export function Parse(...args: any[]): never {
|
||||
const withModuleProperties = typeof args[1] === 'string' ? false : true
|
||||
const [moduleProperties, parser, content, context] = withModuleProperties
|
||||
? [args[0], args[1], args[2], args[3]]
|
||||
: [{}, args[0], args[1], args[2]]
|
||||
return ParseParser(moduleProperties, parser, content, context) as never
|
||||
}
|
||||
247
src/parser/runtime/token.ts
Normal file
247
src/parser/runtime/token.ts
Normal file
@@ -0,0 +1,247 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Chars
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
namespace Chars {
|
||||
/** Returns true if the char code is a whitespace */
|
||||
export function IsWhitespace(value: number): boolean {
|
||||
return value === 32
|
||||
}
|
||||
/** Returns true if the char code is a newline */
|
||||
export function IsNewline(value: number): boolean {
|
||||
return value === 10
|
||||
}
|
||||
/** Returns true if the char code is a alpha */
|
||||
export function IsAlpha(value: number): boolean {
|
||||
return (
|
||||
(value >= 65 && value <= 90) || // A-Z
|
||||
(value >= 97 && value <= 122) // a-z
|
||||
)
|
||||
}
|
||||
/** Returns true if the char code is zero */
|
||||
export function IsZero(value: number): boolean {
|
||||
return value === 48
|
||||
}
|
||||
/** Returns true if the char code is non-zero */
|
||||
export function IsNonZero(value: number): boolean {
|
||||
return value >= 49 && value <= 57
|
||||
}
|
||||
/** Returns true if the char code is a digit */
|
||||
export function IsDigit(value: number): boolean {
|
||||
return (
|
||||
IsNonZero(value) ||
|
||||
IsZero(value)
|
||||
)
|
||||
}
|
||||
/** Returns true if the char code is a dot */
|
||||
export function IsDot(value: number): boolean {
|
||||
return value === 46
|
||||
}
|
||||
/** Returns true if this char code is a underscore */
|
||||
export function IsUnderscore(value: unknown): boolean {
|
||||
return value === 95
|
||||
}
|
||||
/** Returns true if this char code is a dollar sign */
|
||||
export function IsDollarSign(value: unknown): boolean {
|
||||
return value === 36
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Trim
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
namespace Trim {
|
||||
/** Trims Whitespace and retains Newline, Tabspaces, etc. */
|
||||
export function TrimWhitespaceOnly(code: string): string {
|
||||
for (let i = 0; i < code.length; i++) {
|
||||
if (Chars.IsWhitespace(code.charCodeAt(i))) continue
|
||||
return code.slice(i)
|
||||
}
|
||||
return code
|
||||
}
|
||||
/** Trims Whitespace including Newline, Tabspaces, etc. */
|
||||
export function TrimAll(code: string): string {
|
||||
return code.trimStart()
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Const
|
||||
// ------------------------------------------------------------------
|
||||
/** Checks the value matches the next string */
|
||||
// prettier-ignore
|
||||
function NextTokenCheck(value: string, code: string): boolean {
|
||||
if (value.length > code.length) return false
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (value.charCodeAt(i) !== code.charCodeAt(i)) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
/** Gets the next constant string value or empty if no match */
|
||||
// prettier-ignore
|
||||
function NextConst(value: string, code: string, ): [] | [string, string] {
|
||||
return NextTokenCheck(value, code)
|
||||
? [code.slice(0, value.length), code.slice(value.length)]
|
||||
: []
|
||||
}
|
||||
/** Takes the next constant string value skipping any whitespace */
|
||||
// prettier-ignore
|
||||
export function Const(value: string, code: string): [] | [string, string] {
|
||||
if(value.length === 0) return ['', code]
|
||||
const char_0 = value.charCodeAt(0)
|
||||
return (
|
||||
Chars.IsNewline(char_0) ? NextConst(value, Trim.TrimWhitespaceOnly(code)) :
|
||||
Chars.IsWhitespace(char_0) ? NextConst(value, code) :
|
||||
NextConst(value, Trim.TrimAll(code))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Ident
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function IdentIsFirst(char: number) {
|
||||
return (
|
||||
Chars.IsAlpha(char) ||
|
||||
Chars.IsDollarSign(char) ||
|
||||
Chars.IsUnderscore(char)
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IdentIsRest(char: number) {
|
||||
return (
|
||||
Chars.IsAlpha(char) ||
|
||||
Chars.IsDigit(char) ||
|
||||
Chars.IsDollarSign(char) ||
|
||||
Chars.IsUnderscore(char)
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function NextIdent(code: string): [] | [string, string] {
|
||||
if (!IdentIsFirst(code.charCodeAt(0))) return []
|
||||
for (let i = 1; i < code.length; i++) {
|
||||
const char = code.charCodeAt(i)
|
||||
if (IdentIsRest(char)) continue
|
||||
const slice = code.slice(0, i)
|
||||
const rest = code.slice(i)
|
||||
return [slice, rest]
|
||||
}
|
||||
return [code, '']
|
||||
}
|
||||
/** Scans for the next Ident token */
|
||||
// prettier-ignore
|
||||
export function Ident(code: string): [] | [string, string] {
|
||||
return NextIdent(Trim.TrimAll(code))
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Number
|
||||
// ------------------------------------------------------------------
|
||||
/** Checks that the next number is not a leading zero */
|
||||
// prettier-ignore
|
||||
function NumberLeadingZeroCheck(code: string, index: number) {
|
||||
const char_0 = code.charCodeAt(index + 0)
|
||||
const char_1 = code.charCodeAt(index + 1)
|
||||
return (
|
||||
(
|
||||
// 1-9
|
||||
Chars.IsNonZero(char_0)
|
||||
) || (
|
||||
// 0
|
||||
Chars.IsZero(char_0) &&
|
||||
!Chars.IsDigit(char_1)
|
||||
) || (
|
||||
// 0.
|
||||
Chars.IsZero(char_0) &&
|
||||
Chars.IsDot(char_1)
|
||||
) || (
|
||||
// .0
|
||||
Chars.IsDot(char_0) &&
|
||||
Chars.IsDigit(char_1)
|
||||
)
|
||||
)
|
||||
}
|
||||
/** Gets the next number token */
|
||||
// prettier-ignore
|
||||
function NextNumber(code: string): [] | [string, string] {
|
||||
const negated = code.charAt(0) === '-'
|
||||
const index = negated ? 1 : 0
|
||||
if (!NumberLeadingZeroCheck(code, index)) {
|
||||
return []
|
||||
}
|
||||
const dash = negated ? '-' : ''
|
||||
let hasDot = false
|
||||
for (let i = index; i < code.length; i++) {
|
||||
const char_i = code.charCodeAt(i)
|
||||
if (Chars.IsDigit(char_i)) {
|
||||
continue
|
||||
}
|
||||
if (Chars.IsDot(char_i)) {
|
||||
if (hasDot) {
|
||||
const slice = code.slice(index, i)
|
||||
const rest = code.slice(i)
|
||||
return [`${dash}${slice}`, rest]
|
||||
}
|
||||
hasDot = true
|
||||
continue
|
||||
}
|
||||
const slice = code.slice(index, i)
|
||||
const rest = code.slice(i)
|
||||
return [`${dash}${slice}`, rest]
|
||||
}
|
||||
return [code, '']
|
||||
}
|
||||
/** Scans for the next number token */
|
||||
// prettier-ignore
|
||||
export function Number(code: string) {
|
||||
return NextNumber(Trim.TrimAll(code))
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// String
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function NextString(options: string[], code: string): [] | [string, string] {
|
||||
const first = code.charAt(0)
|
||||
if(!options.includes(first)) return []
|
||||
const quote = first
|
||||
for(let i = 1; i < code.length; i++) {
|
||||
const char = code.charAt(i)
|
||||
if(char === quote) {
|
||||
const slice = code.slice(1, i)
|
||||
const rest = code.slice(i + 1)
|
||||
return [slice, rest]
|
||||
}
|
||||
}
|
||||
return []
|
||||
}
|
||||
/** Scans the next Literal String value */
|
||||
// prettier-ignore
|
||||
export function String(options: string[], code: string) {
|
||||
return NextString(options, Trim.TrimAll(code))
|
||||
}
|
||||
250
src/parser/runtime/types.ts
Normal file
250
src/parser/runtime/types.ts
Normal file
@@ -0,0 +1,250 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export type IModuleProperties = Record<PropertyKey, IParser>
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Static
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/** Force output static type evaluation for Arrays */
|
||||
export type StaticEnsure<T> = T extends infer R ? R : never
|
||||
|
||||
/** Infers the Output Parameter for a Parser */
|
||||
export type StaticParser<Parser extends IParser> = Parser extends IParser<infer Output extends unknown> ? Output : unknown
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Mapping
|
||||
// ------------------------------------------------------------------
|
||||
export type IMapping<Input extends unknown = any, Output extends unknown = unknown> = (input: Input, context: any) => Output
|
||||
|
||||
/** Maps input to output. This is the default Mapping */
|
||||
export const Identity = (value: unknown) => value
|
||||
|
||||
/** Maps the output as the given parameter T */
|
||||
// prettier-ignore
|
||||
export const As = <T>(mapping: T): ((value: unknown) => T) => (_: unknown) => mapping
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Parser
|
||||
// ------------------------------------------------------------------
|
||||
export interface IParser<Output extends unknown = unknown> {
|
||||
type: string
|
||||
mapping: IMapping<any, Output>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Context
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type ContextParameter<_Left extends IParser, Right extends IParser> = (
|
||||
StaticParser<Right>
|
||||
)
|
||||
export interface IContext<Output extends unknown = unknown> extends IParser<Output> {
|
||||
type: 'Context'
|
||||
left: IParser
|
||||
right: IParser
|
||||
}
|
||||
/** `[Context]` Creates a Context Parser */
|
||||
export function Context<Left extends IParser, Right extends IParser, Mapping extends IMapping = IMapping<ContextParameter<Left, Right>>>(left: Left, right: Right, mapping: Mapping): IContext<ReturnType<Mapping>>
|
||||
/** `[Context]` Creates a Context Parser */
|
||||
export function Context<Left extends IParser, Right extends IParser>(left: Left, right: Right): IContext<ContextParameter<Left, Right>>
|
||||
/** `[Context]` Creates a Context Parser */
|
||||
export function Context(...args: unknown[]): never {
|
||||
const [left, right, mapping] = args.length === 3 ? [args[0], args[1], args[2]] : [args[0], args[1], Identity]
|
||||
return { type: 'Context', left, right, mapping } as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Array
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type ArrayParameter<Parser extends IParser> = StaticEnsure<
|
||||
StaticParser<Parser>[]
|
||||
>
|
||||
export interface IArray<Output extends unknown = unknown> extends IParser<Output> {
|
||||
type: 'Array'
|
||||
parser: IParser
|
||||
}
|
||||
/** `[EBNF]` Creates an Array Parser */
|
||||
export function Array<Parser extends IParser, Mapping extends IMapping = IMapping<ArrayParameter<Parser>>>(parser: Parser, mapping: Mapping): IArray<ReturnType<Mapping>>
|
||||
/** `[EBNF]` Creates an Array Parser */
|
||||
export function Array<Parser extends IParser>(parser: Parser): IArray<ArrayParameter<Parser>>
|
||||
/** `[EBNF]` Creates an Array Parser */
|
||||
export function Array(...args: unknown[]): never {
|
||||
const [parser, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity]
|
||||
return { type: 'Array', parser, mapping } as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Const
|
||||
// ------------------------------------------------------------------
|
||||
export interface IConst<Output extends unknown = unknown> extends IParser<Output> {
|
||||
type: 'Const'
|
||||
value: string
|
||||
}
|
||||
/** `[TERM]` Creates a Const Parser */
|
||||
export function Const<Value extends string, Mapping extends IMapping<Value>>(value: Value, mapping: Mapping): IConst<ReturnType<Mapping>>
|
||||
/** `[TERM]` Creates a Const Parser */
|
||||
export function Const<Value extends string>(value: Value): IConst<Value>
|
||||
/** `[TERM]` Creates a Const Parser */
|
||||
export function Const(...args: unknown[]): never {
|
||||
const [value, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity]
|
||||
return { type: 'Const', value, mapping } as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Ref
|
||||
// ------------------------------------------------------------------
|
||||
export interface IRef<Output extends unknown = unknown> extends IParser<Output> {
|
||||
type: 'Ref'
|
||||
ref: string
|
||||
}
|
||||
/** `[BNF]` Creates a Ref Parser. This Parser can only be used in the context of a Module */
|
||||
export function Ref<Type extends unknown, Mapping extends IMapping<Type>>(ref: string, mapping: Mapping): IRef<ReturnType<Mapping>>
|
||||
/** `[BNF]` Creates a Ref Parser. This Parser can only be used in the context of a Module */
|
||||
export function Ref<Type extends unknown>(ref: string): IRef<Type>
|
||||
/** `[BNF]` Creates a Ref Parser. This Parser can only be used in the context of a Module */
|
||||
export function Ref(...args: unknown[]): never {
|
||||
const [ref, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity]
|
||||
return { type: 'Ref', ref, mapping } as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// String
|
||||
// ------------------------------------------------------------------
|
||||
export interface IString<Output extends unknown = unknown> extends IParser<Output> {
|
||||
type: 'String'
|
||||
options: string[]
|
||||
}
|
||||
/** `[TERM]` Creates a String Parser. Options are an array of permissable quote characters */
|
||||
export function String<Mapping extends IMapping<string>>(options: string[], mapping: Mapping): IString<ReturnType<Mapping>>
|
||||
/** `[TERM]` Creates a String Parser. Options are an array of permissable quote characters */
|
||||
export function String(options: string[]): IString<string>
|
||||
/** `[TERM]` Creates a String Parser. Options are an array of permissable quote characters */
|
||||
export function String(...params: unknown[]): never {
|
||||
const [options, mapping] = params.length === 2 ? [params[0], params[1]] : [params[0], Identity]
|
||||
return { type: 'String', options, mapping } as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Ident
|
||||
// ------------------------------------------------------------------
|
||||
export interface IIdent<Output extends unknown = unknown> extends IParser<Output> {
|
||||
type: 'Ident'
|
||||
}
|
||||
/** `[TERM]` Creates an Ident Parser where Ident matches any valid JavaScript identifier */
|
||||
export function Ident<Mapping extends IMapping<string>>(mapping: Mapping): IIdent<ReturnType<Mapping>>
|
||||
/** `[TERM]` Creates an Ident Parser where Ident matches any valid JavaScript identifier */
|
||||
export function Ident(): IIdent<string>
|
||||
/** `[TERM]` Creates an Ident Parser where Ident matches any valid JavaScript identifier */
|
||||
export function Ident(...params: unknown[]): never {
|
||||
const mapping = params.length === 1 ? params[0] : Identity
|
||||
return { type: 'Ident', mapping } as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Number
|
||||
// ------------------------------------------------------------------
|
||||
export interface INumber<Output extends unknown = unknown> extends IParser<Output> {
|
||||
type: 'Number'
|
||||
}
|
||||
/** `[TERM]` Creates an Number Parser */
|
||||
export function Number<Mapping extends IMapping<string>>(mapping: Mapping): INumber<ReturnType<Mapping>>
|
||||
/** `[TERM]` Creates an Number Parser */
|
||||
export function Number(): INumber<string>
|
||||
/** `[TERM]` Creates an Number Parser */
|
||||
export function Number(...params: unknown[]): never {
|
||||
const mapping = params.length === 1 ? params[0] : Identity
|
||||
return { type: 'Number', mapping } as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Optional
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type OptionalParameter<Parser extends IParser, Result extends unknown = [StaticParser<Parser>] | []> = (
|
||||
Result
|
||||
)
|
||||
export interface IOptional<Output extends unknown = unknown> extends IParser<Output> {
|
||||
type: 'Optional'
|
||||
parser: IParser
|
||||
}
|
||||
/** `[EBNF]` Creates an Optional Parser */
|
||||
export function Optional<Parser extends IParser, Mapping extends IMapping = IMapping<OptionalParameter<Parser>>>(parser: Parser, mapping: Mapping): IOptional<ReturnType<Mapping>>
|
||||
/** `[EBNF]` Creates an Optional Parser */
|
||||
export function Optional<Parser extends IParser>(parser: Parser): IOptional<OptionalParameter<Parser>>
|
||||
/** `[EBNF]` Creates an Optional Parser */
|
||||
export function Optional(...args: unknown[]): never {
|
||||
const [parser, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity]
|
||||
return { type: 'Optional', parser, mapping } as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Tuple
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TupleParameter<Parsers extends IParser[], Result extends unknown[] = []> = StaticEnsure<
|
||||
Parsers extends [infer Left extends IParser, ...infer Right extends IParser[]]
|
||||
? TupleParameter<Right, [...Result, StaticEnsure<StaticParser<Left>>]>
|
||||
: Result
|
||||
>
|
||||
export interface ITuple<Output extends unknown = unknown> extends IParser<Output> {
|
||||
type: 'Tuple'
|
||||
parsers: IParser[]
|
||||
}
|
||||
/** `[BNF]` Creates a Tuple Parser */
|
||||
export function Tuple<Parsers extends IParser[], Mapping extends IMapping = IMapping<TupleParameter<Parsers>>>(parsers: [...Parsers], mapping: Mapping): ITuple<ReturnType<Mapping>>
|
||||
/** `[BNF]` Creates a Tuple Parser */
|
||||
export function Tuple<Parsers extends IParser[]>(parsers: [...Parsers]): ITuple<TupleParameter<Parsers>>
|
||||
/** `[BNF]` Creates a Tuple Parser */
|
||||
export function Tuple(...args: unknown[]): never {
|
||||
const [parsers, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity]
|
||||
return { type: 'Tuple', parsers, mapping } as never
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Union
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type UnionParameter<Parsers extends IParser[], Result extends unknown = never> = StaticEnsure<
|
||||
Parsers extends [infer Left extends IParser, ...infer Right extends IParser[]]
|
||||
? UnionParameter<Right, Result | StaticParser<Left>>
|
||||
: Result
|
||||
>
|
||||
export interface IUnion<Output extends unknown = unknown> extends IParser<Output> {
|
||||
type: 'Union'
|
||||
parsers: IParser[]
|
||||
}
|
||||
/** `[BNF]` Creates a Union parser */
|
||||
export function Union<Parsers extends IParser[], Mapping extends IMapping = IMapping<UnionParameter<Parsers>>>(parsers: [...Parsers], mapping: Mapping): IUnion<ReturnType<Mapping>>
|
||||
/** `[BNF]` Creates a Union parser */
|
||||
export function Union<Parsers extends IParser[]>(parsers: [...Parsers]): IUnion<UnionParameter<Parsers>>
|
||||
/** `[BNF]` Creates a Union parser */
|
||||
export function Union(...args: unknown[]): never {
|
||||
const [parsers, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity]
|
||||
return { type: 'Union', parsers, mapping } as never
|
||||
}
|
||||
31
src/parser/static/index.ts
Normal file
31
src/parser/static/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * as Token from './token'
|
||||
export * from './parse'
|
||||
export * from './types'
|
||||
153
src/parser/static/parse.ts
Normal file
153
src/parser/static/parse.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import * as Tokens from './token'
|
||||
import * as Types from './types'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Context
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type ContextParser<Left extends Types.IParser, Right extends Types.IParser, Code extends string, Context extends unknown> = (
|
||||
Parse<Left, Code, Context> extends [infer Context extends unknown, infer Rest extends string]
|
||||
? Parse<Right, Rest, Context>
|
||||
: []
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Array
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type ArrayParser<Parser extends Types.IParser, Code extends string, Context extends unknown, Result extends unknown[] = []> = (
|
||||
Parse<Parser, Code, Context> extends [infer Value1 extends unknown, infer Rest extends string]
|
||||
? ArrayParser<Parser, Rest, Context, [...Result, Value1]>
|
||||
: [Result, Code]
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Const
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type ConstParser<Value extends string, Code extends string, _Context extends unknown> = (
|
||||
Tokens.Const<Value, Code> extends [infer Match extends Value, infer Rest extends string]
|
||||
? [Match, Rest]
|
||||
: []
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Ident
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type IdentParser<Code extends string, _Context extends unknown> = (
|
||||
Tokens.Ident<Code> extends [infer Match extends string, infer Rest extends string]
|
||||
? [Match, Rest]
|
||||
: []
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Number
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type NumberParser<Code extends string, _Context extends unknown> = (
|
||||
Tokens.Number<Code> extends [infer Match extends string, infer Rest extends string]
|
||||
? [Match, Rest]
|
||||
: []
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Optional
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type OptionalParser<Parser extends Types.IParser, Code extends string, Context extends unknown> = (
|
||||
Parse<Parser, Code, Context> extends [infer Value extends unknown, infer Rest extends string]
|
||||
? [[Value], Rest]
|
||||
: [[], Code]
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// String
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type StringParser<Options extends string[], Code extends string, _Context extends unknown> = (
|
||||
Tokens.String<Options, Code> extends [infer Match extends string, infer Rest extends string]
|
||||
? [Match, Rest]
|
||||
: []
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Tuple
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TupleParser<Parsers extends Types.IParser[], Code extends string, Context extends unknown, Result extends unknown[] = []> = (
|
||||
Parsers extends [infer Left extends Types.IParser, ...infer Right extends Types.IParser[]]
|
||||
? Parse<Left, Code, Context> extends [infer Value extends unknown, infer Rest extends string]
|
||||
? TupleParser<Right, Rest, Context, [...Result, Value]>
|
||||
: []
|
||||
: [Result, Code]
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Union
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type UnionParser<Parsers extends Types.IParser[], Code extends string, Context extends unknown> = (
|
||||
Parsers extends [infer Left extends Types.IParser, ...infer Right extends Types.IParser[]]
|
||||
? Parse<Left, Code, Context> extends [infer Value extends unknown, infer Rest extends string]
|
||||
? [Value, Rest]
|
||||
: UnionParser<Right, Code, Context>
|
||||
: []
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Parse
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type ParseCode<Type extends Types.IParser, Code extends string, Context extends unknown = unknown> = (
|
||||
Type extends Types.Context<infer Left extends Types.IParser, infer Right extends Types.IParser> ? ContextParser<Left, Right, Code, Context> :
|
||||
Type extends Types.Array<infer Parser extends Types.IParser> ? ArrayParser<Parser, Code, Context> :
|
||||
Type extends Types.Const<infer Value extends string> ? ConstParser<Value, Code, Context> :
|
||||
Type extends Types.Ident ? IdentParser<Code, Context> :
|
||||
Type extends Types.Number ? NumberParser<Code, Context> :
|
||||
Type extends Types.Optional<infer Parser extends Types.IParser> ? OptionalParser<Parser, Code, Context> :
|
||||
Type extends Types.String<infer Options extends string[]> ? StringParser<Options, Code, Context> :
|
||||
Type extends Types.Tuple<infer Parsers extends Types.IParser[]> ? TupleParser<Parsers, Code, Context> :
|
||||
Type extends Types.Union<infer Parsers extends Types.IParser[]> ? UnionParser<Parsers, Code, Context> :
|
||||
[]
|
||||
)
|
||||
// prettier-ignore
|
||||
type ParseMapping<Parser extends Types.IParser, Result extends unknown, Context extends unknown = unknown> = (
|
||||
(Parser['mapping'] & { input: Result, context: Context })['output']
|
||||
)
|
||||
|
||||
/** Parses code with the given parser */
|
||||
// prettier-ignore
|
||||
export type Parse<Type extends Types.IParser, Code extends string, Context extends unknown = unknown> = (
|
||||
ParseCode<Type, Code, Context> extends [infer L extends unknown, infer R extends string]
|
||||
? [ParseMapping<Type, L, Context>, R]
|
||||
: []
|
||||
)
|
||||
213
src/parser/static/token.ts
Normal file
213
src/parser/static/token.ts
Normal file
@@ -0,0 +1,213 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Chars
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
namespace Chars {
|
||||
export type Empty = ''
|
||||
export type Space = ' '
|
||||
export type Newline = '\n'
|
||||
export type Dot = '.'
|
||||
export type Hyphen = '-'
|
||||
export type Digit = [
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
|
||||
]
|
||||
export type Alpha = [
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
|
||||
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
|
||||
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z'
|
||||
]
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Trim
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
namespace Trim {
|
||||
// ------------------------------------------------------------------
|
||||
// Whitespace Filters
|
||||
// ------------------------------------------------------------------
|
||||
type W9 = `${W8}${W8}` // 512
|
||||
type W8 = `${W7}${W7}` // 256
|
||||
type W7 = `${W6}${W6}` // 128
|
||||
type W6 = `${W5}${W5}` // 64
|
||||
type W5 = `${W4}${W4}` // 32
|
||||
type W4 = `${W3}${W3}` // 16
|
||||
type W3 = `${W2}${W2}` // 8
|
||||
type W2 = `${W1}${W1}` // 4
|
||||
type W1 = `${W0}${W0}` // 2
|
||||
type W0 = ` ` // 1
|
||||
// ------------------------------------------------------------------
|
||||
// TrimWhitespace
|
||||
// ------------------------------------------------------------------
|
||||
/** Trims whitespace only */
|
||||
export type TrimWhitespace<Code extends string> = (
|
||||
Code extends `${W4}${infer Rest extends string}` ? TrimWhitespace<Rest> :
|
||||
Code extends `${W3}${infer Rest extends string}` ? TrimWhitespace<Rest> :
|
||||
Code extends `${W1}${infer Rest extends string}` ? TrimWhitespace<Rest> :
|
||||
Code extends `${W0}${infer Rest extends string}` ? TrimWhitespace<Rest> :
|
||||
Code
|
||||
)
|
||||
// ------------------------------------------------------------------
|
||||
// Trim
|
||||
// ------------------------------------------------------------------
|
||||
/** Trims Whitespace and Newline */
|
||||
export type TrimAll<Code extends string> = (
|
||||
Code extends `${W4}${infer Rest extends string}` ? TrimAll<Rest> :
|
||||
Code extends `${W3}${infer Rest extends string}` ? TrimAll<Rest> :
|
||||
Code extends `${W1}${infer Rest extends string}` ? TrimAll<Rest> :
|
||||
Code extends `${W0}${infer Rest extends string}` ? TrimAll<Rest> :
|
||||
Code extends `${Chars.Newline}${infer Rest extends string}` ? TrimAll<Rest> :
|
||||
Code
|
||||
)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Union
|
||||
// ------------------------------------------------------------------
|
||||
/** Scans for the next match union */
|
||||
// prettier-ignore
|
||||
type NextUnion<Variants extends string[], Code extends string> = (
|
||||
Variants extends [infer Variant extends string, ...infer Rest1 extends string[]]
|
||||
? NextConst<Variant, Code> extends [infer Match extends string, infer Rest2 extends string]
|
||||
? [Match, Rest2]
|
||||
: NextUnion<Rest1, Code>
|
||||
: []
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Const
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type NextConst<Value extends string, Code extends string> = (
|
||||
Code extends `${Value}${infer Rest extends string}`
|
||||
? [Value, Rest]
|
||||
: []
|
||||
)
|
||||
/** Scans for the next constant value */
|
||||
// prettier-ignore
|
||||
export type Const<Value extends string, Code extends string> = (
|
||||
Value extends '' ? ['', Code] :
|
||||
Value extends `${infer First extends string}${string}`
|
||||
? (
|
||||
First extends Chars.Newline ? NextConst<Value, Trim.TrimWhitespace<Code>> :
|
||||
First extends Chars.Space ? NextConst<Value, Code> :
|
||||
NextConst<Value, Trim.TrimAll<Code>>
|
||||
) : never
|
||||
)
|
||||
// ------------------------------------------------------------------
|
||||
// Number
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type NextNumberNegate<Code extends string> = (
|
||||
Code extends `${Chars.Hyphen}${infer Rest extends string}`
|
||||
? [Chars.Hyphen, Rest]
|
||||
: [Chars.Empty, Code]
|
||||
)
|
||||
// prettier-ignore
|
||||
type NextNumberZeroCheck<Code extends string> = (
|
||||
Code extends `0${infer Rest}`
|
||||
? NextUnion<Chars.Digit, Rest> extends [string, string] ? false : true
|
||||
: true
|
||||
)
|
||||
// prettier-ignore
|
||||
type NextNumberScan<Code extends string, HasDecimal extends boolean = false, Result extends string = Chars.Empty> = (
|
||||
NextUnion<[...Chars.Digit, Chars.Dot], Code> extends [infer Char extends string, infer Rest extends string]
|
||||
? Char extends Chars.Dot
|
||||
? HasDecimal extends false
|
||||
? NextNumberScan<Rest, true, `${Result}${Char}`>
|
||||
: [Result, `.${Rest}`]
|
||||
: NextNumberScan<Rest, HasDecimal, `${Result}${Char}`>
|
||||
: [Result, Code]
|
||||
)
|
||||
// prettier-ignore
|
||||
export type NextNumber<Code extends string> = (
|
||||
NextNumberNegate<Code> extends [infer Negate extends string, infer Rest extends string]
|
||||
? NextNumberZeroCheck<Rest> extends true
|
||||
? NextNumberScan<Rest> extends [infer Number extends string, infer Rest2 extends string]
|
||||
? Number extends Chars.Empty
|
||||
? []
|
||||
: [`${Negate}${Number}`, Rest2]
|
||||
: []
|
||||
: []
|
||||
: []
|
||||
)
|
||||
/** Scans for the next literal number */
|
||||
export type Number<Code extends string> = NextNumber<Trim.TrimAll<Code>>
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// String
|
||||
// ------------------------------------------------------------------
|
||||
type NextStringQuote<Options extends string[], Code extends string> = NextUnion<Options, Code>
|
||||
// prettier-ignore
|
||||
type NextStringBody<Code extends string, Quote extends string, Result extends string = Chars.Empty> = (
|
||||
Code extends `${infer Char extends string}${infer Rest extends string}`
|
||||
? Char extends Quote
|
||||
? [Result, Rest]
|
||||
: NextStringBody<Rest, Quote, `${Result}${Char}`>
|
||||
: []
|
||||
)
|
||||
// prettier-ignore
|
||||
type NextString<Options extends string[], Code extends string> = (
|
||||
NextStringQuote<Options, Code> extends [infer Quote extends string, infer Rest extends string]
|
||||
? NextStringBody<Rest, Quote> extends [infer String extends string, infer Rest extends string]
|
||||
? [String, Rest]
|
||||
: []
|
||||
: []
|
||||
)
|
||||
/** Scans for the next literal string */
|
||||
export type String<Options extends string[], Code extends string> = NextString<Options, Trim.TrimAll<Code>>
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Ident
|
||||
// ------------------------------------------------------------------
|
||||
type IdentLeft = [...Chars.Alpha, '_', '$'] // permissable first characters
|
||||
type IdentRight = [...Chars.Digit, ...IdentLeft] // permissible subsequent characters
|
||||
|
||||
// prettier-ignore
|
||||
type NextIdentScan<Code extends string, Result extends string = Chars.Empty> = (
|
||||
NextUnion<IdentRight, Code> extends [infer Char extends string, infer Rest extends string]
|
||||
? NextIdentScan<Rest, `${Result}${Char}`>
|
||||
: [Result, Code]
|
||||
)
|
||||
// prettier-ignore
|
||||
type NextIdent<Code extends string> = (
|
||||
NextUnion<IdentLeft, Code> extends [infer Left extends string, infer Rest1 extends string]
|
||||
? NextIdentScan<Rest1> extends [infer Right extends string, infer Rest2 extends string]
|
||||
? [`${Left}${Right}`, Rest2]
|
||||
: []
|
||||
: []
|
||||
)
|
||||
|
||||
/** Scans for the next Ident */
|
||||
export type Ident<Code extends string> = NextIdent<Trim.TrimAll<Code>>
|
||||
143
src/parser/static/types.ts
Normal file
143
src/parser/static/types.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/parsebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Mapping
|
||||
// ------------------------------------------------------------------
|
||||
/**
|
||||
* `[ACTION]` Inference mapping base type. Used to specify semantic actions for
|
||||
* Parser productions. This type is implemented as a higher-kinded type where
|
||||
* productions are received on the `input` property with mapping assigned
|
||||
* the `output` property. The parsing context is available on the `context`
|
||||
* property.
|
||||
*/
|
||||
export interface IMapping {
|
||||
context: unknown
|
||||
input: unknown
|
||||
output: unknown
|
||||
}
|
||||
|
||||
/** `[ACTION]` Default inference mapping. */
|
||||
export interface Identity extends IMapping {
|
||||
output: this['input']
|
||||
}
|
||||
|
||||
/** `[ACTION]` Maps the given argument `T` as the mapping output */
|
||||
export interface As<T> extends IMapping {
|
||||
output: T
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Parser
|
||||
// ------------------------------------------------------------------
|
||||
/** Base type Parser implemented by all other parsers */
|
||||
export interface IParser<Mapping extends IMapping = Identity> {
|
||||
type: string
|
||||
mapping: Mapping
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Context
|
||||
// ------------------------------------------------------------------
|
||||
/** `[Context]` Creates a Context Parser */
|
||||
export interface Context<Left extends IParser = IParser, Right extends IParser = IParser, Mapping extends IMapping = Identity> extends IParser<Mapping> {
|
||||
type: 'Context'
|
||||
left: Left
|
||||
right: Right
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Array
|
||||
// ------------------------------------------------------------------
|
||||
/** `[EBNF]` Creates an Array Parser */
|
||||
export interface Array<Parser extends IParser = IParser, Mapping extends IMapping = Identity> extends IParser<Mapping> {
|
||||
type: 'Array'
|
||||
parser: Parser
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Const
|
||||
// ------------------------------------------------------------------
|
||||
/** `[TERM]` Creates a Const Parser */
|
||||
export interface Const<Value extends string = string, Mapping extends IMapping = Identity> extends IParser<Mapping> {
|
||||
type: 'Const'
|
||||
value: Value
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Ident
|
||||
// ------------------------------------------------------------------
|
||||
/** `[TERM]` Creates an Ident Parser. */
|
||||
// prettier-ignore
|
||||
export interface Ident<Mapping extends IMapping = Identity> extends IParser<Mapping> {
|
||||
type: 'Ident'
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Number
|
||||
// ------------------------------------------------------------------
|
||||
/** `[TERM]` Creates a Number Parser. */
|
||||
// prettier-ignore
|
||||
export interface Number<Mapping extends IMapping = Identity> extends IParser<Mapping> {
|
||||
type: 'Number'
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Optional
|
||||
// ------------------------------------------------------------------
|
||||
/** `[EBNF]` Creates a Optional Parser */
|
||||
export interface Optional<Parser extends IParser = IParser, Mapping extends IMapping = Identity> extends IParser<Mapping> {
|
||||
type: 'Optional'
|
||||
parser: Parser
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// String
|
||||
// ------------------------------------------------------------------
|
||||
/** `[TERM]` Creates a String Parser. Options are an array of permissable quote characters */
|
||||
export interface String<Options extends string[], Mapping extends IMapping = Identity> extends IParser<Mapping> {
|
||||
type: 'String'
|
||||
quote: Options
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Tuple
|
||||
// ------------------------------------------------------------------
|
||||
/** `[BNF]` Creates a Tuple Parser */
|
||||
export interface Tuple<Parsers extends IParser[] = [], Mapping extends IMapping = Identity> extends IParser<Mapping> {
|
||||
type: 'Tuple'
|
||||
parsers: [...Parsers]
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Union
|
||||
// ------------------------------------------------------------------
|
||||
/** `[BNF]` Creates a Union Parser */
|
||||
export interface Union<Parsers extends IParser[] = [], Mapping extends IMapping = Identity> extends IParser<Mapping> {
|
||||
type: 'Union'
|
||||
parsers: [...Parsers]
|
||||
}
|
||||
29
src/syntax/index.ts
Normal file
29
src/syntax/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/syntax
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './syntax'
|
||||
1030
src/syntax/mapping.ts
Normal file
1030
src/syntax/mapping.ts
Normal file
File diff suppressed because it is too large
Load Diff
1686
src/syntax/parser.ts
Normal file
1686
src/syntax/parser.ts
Normal file
File diff suppressed because it is too large
Load Diff
62
src/syntax/syntax.ts
Normal file
62
src/syntax/syntax.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/syntax
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import * as t from '../type/index'
|
||||
import { Type, TType } from './parser'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// NoInfer
|
||||
// ------------------------------------------------------------------
|
||||
/** `[Experimental]` Parses type expressions into TypeBox types but does not infer */
|
||||
export function NoInfer<Context extends Record<PropertyKey, t.TSchema>, Input extends string>(context: Context, input: Input, options?: t.SchemaOptions): t.TSchema
|
||||
/** `[Experimental]` Parses type expressions into TypeBox types but does not infer */
|
||||
export function NoInfer<Input extends string>(input: Input, options?: t.SchemaOptions): t.TSchema
|
||||
/** `[Experimental]` Parses type expressions into TypeBox types but does not infer */
|
||||
// prettier-ignore
|
||||
export function NoInfer(...args: any[]): t.TSchema {
|
||||
const withContext = typeof args[0] === 'string' ? false : true
|
||||
const [context, code, options] = withContext ? [args[0], args[1], args[2] || {}] : [{}, args[0], args[1] || {}]
|
||||
const result = Type(code, context)[0]
|
||||
return t.KindGuard.IsSchema(result)
|
||||
? t.CloneType(result, options)
|
||||
: t.Never(options)
|
||||
}
|
||||
|
||||
/** `[Experimental]` Parses type expressions into TypeBox types */
|
||||
// prettier-ignore
|
||||
export type TSyntax<Context extends Record<PropertyKey, t.TSchema>, Code extends string> = (
|
||||
TType<Code, Context> extends [infer Type extends t.TSchema, string] ? Type : t.TNever
|
||||
)
|
||||
/** `[Experimental]` Parses type expressions into TypeBox types */
|
||||
export function Syntax<Context extends Record<PropertyKey, t.TSchema>, Input extends string>(context: Context, input: Input, options?: t.SchemaOptions): TSyntax<Context, Input>
|
||||
/** `[Experimental]` Parses type expressions into TypeBox types */
|
||||
export function Syntax<Input extends string>(annotation: Input, options?: t.SchemaOptions): TSyntax<{}, Input>
|
||||
/** `[Experimental]` Parses type expressions into TypeBox types */
|
||||
export function Syntax(...args: any[]): never {
|
||||
return NoInfer.apply(null, args as never) as never
|
||||
}
|
||||
30
src/system/index.ts
Normal file
30
src/system/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/system
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './policy'
|
||||
export * from './system'
|
||||
77
src/system/policy.ts
Normal file
77
src/system/policy.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/system
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { IsObject, IsArray, IsNumber, IsUndefined } from '../value/guard/index'
|
||||
|
||||
export namespace TypeSystemPolicy {
|
||||
// ------------------------------------------------------------------
|
||||
// TypeSystemPolicy: Instancing
|
||||
// ------------------------------------------------------------------
|
||||
/**
|
||||
* Configures the instantiation behavior of TypeBox types. The `default` option assigns raw JavaScript
|
||||
* references for embedded types, which may cause side effects if type properties are explicitly updated
|
||||
* outside the TypeBox type builder. The `clone` option creates copies of any shared types upon creation,
|
||||
* preventing unintended side effects. The `freeze` option applies `Object.freeze()` to the type, making
|
||||
* it fully readonly and immutable. Implementations should use `default` whenever possible, as it is the
|
||||
* fastest way to instantiate types. The default setting is `default`.
|
||||
*/
|
||||
export let InstanceMode: 'default' | 'clone' | 'freeze' = 'default'
|
||||
// ------------------------------------------------------------------
|
||||
// TypeSystemPolicy: Checking
|
||||
// ------------------------------------------------------------------
|
||||
/** Sets whether TypeBox should assert optional properties using the TypeScript `exactOptionalPropertyTypes` assertion policy. The default is `false` */
|
||||
export let ExactOptionalPropertyTypes: boolean = false
|
||||
/** Sets whether arrays should be treated as a kind of objects. The default is `false` */
|
||||
export let AllowArrayObject: boolean = false
|
||||
/** Sets whether `NaN` or `Infinity` should be treated as valid numeric values. The default is `false` */
|
||||
export let AllowNaN: boolean = false
|
||||
/** Sets whether `null` should validate for void types. The default is `false` */
|
||||
export let AllowNullVoid: boolean = false
|
||||
/** Checks this value using the ExactOptionalPropertyTypes policy */
|
||||
export function IsExactOptionalProperty(value: Record<keyof any, unknown>, key: string) {
|
||||
return ExactOptionalPropertyTypes ? key in value : value[key] !== undefined
|
||||
}
|
||||
/** Checks this value using the AllowArrayObjects policy */
|
||||
export function IsObjectLike(value: unknown): value is Record<keyof any, unknown> {
|
||||
const isObject = IsObject(value)
|
||||
return AllowArrayObject ? isObject : isObject && !IsArray(value)
|
||||
}
|
||||
/** Checks this value as a record using the AllowArrayObjects policy */
|
||||
export function IsRecordLike(value: unknown): value is Record<keyof any, unknown> {
|
||||
return IsObjectLike(value) && !(value instanceof Date) && !(value instanceof Uint8Array)
|
||||
}
|
||||
/** Checks this value using the AllowNaN policy */
|
||||
export function IsNumberLike(value: unknown): value is number {
|
||||
return AllowNaN ? IsNumber(value) : Number.isFinite(value)
|
||||
}
|
||||
/** Checks this value using the AllowVoidNull policy */
|
||||
export function IsVoidLike(value: unknown): value is void {
|
||||
const isUndefined = IsUndefined(value)
|
||||
return AllowNullVoid ? isUndefined || value === null : isUndefined
|
||||
}
|
||||
}
|
||||
66
src/system/system.ts
Normal file
66
src/system/system.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/system
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { TypeRegistry, FormatRegistry } from '../type/registry/index'
|
||||
import { Unsafe, type TUnsafe } from '../type/unsafe/index'
|
||||
import { Kind } from '../type/symbols/index'
|
||||
import { TypeBoxError } from '../type/error/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Errors
|
||||
// ------------------------------------------------------------------
|
||||
export class TypeSystemDuplicateTypeKind extends TypeBoxError {
|
||||
constructor(kind: string) {
|
||||
super(`Duplicate type kind '${kind}' detected`)
|
||||
}
|
||||
}
|
||||
export class TypeSystemDuplicateFormat extends TypeBoxError {
|
||||
constructor(kind: string) {
|
||||
super(`Duplicate string format '${kind}' detected`)
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TypeSystem
|
||||
// ------------------------------------------------------------------
|
||||
export type TypeFactoryFunction<Type, Options = Record<PropertyKey, unknown>> = (options?: Partial<Options>) => TUnsafe<Type>
|
||||
|
||||
/** Creates user defined types and formats and provides overrides for value checking behaviours */
|
||||
export namespace TypeSystem {
|
||||
/** Creates a new type */
|
||||
export function Type<Type, Options = Record<PropertyKey, unknown>>(kind: string, check: (options: Options, value: unknown) => boolean): TypeFactoryFunction<Type, Options> {
|
||||
if (TypeRegistry.Has(kind)) throw new TypeSystemDuplicateTypeKind(kind)
|
||||
TypeRegistry.Set(kind, check)
|
||||
return (options: Partial<Options> = {}) => Unsafe<Type>({ ...options, [Kind]: kind })
|
||||
}
|
||||
/** Creates a new string format */
|
||||
export function Format<F extends string>(format: F, check: (value: string) => boolean): F {
|
||||
if (FormatRegistry.Has(format)) throw new TypeSystemDuplicateFormat(format)
|
||||
FormatRegistry.Set(format, check)
|
||||
return format
|
||||
}
|
||||
}
|
||||
4
src/tsconfig.json
Normal file
4
src/tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"files": ["compiler/index.ts", "errors/index.ts", "parser/index.ts", "syntax/index.ts", "system/index.ts", "type/index.ts", "value/index.ts", "index.ts"]
|
||||
}
|
||||
41
src/type/any/any.ts
Normal file
41
src/type/any/any.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/index'
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
export interface TAny extends TSchema {
|
||||
[Kind]: 'Any'
|
||||
static: any
|
||||
}
|
||||
|
||||
/** `[Json]` Creates an Any type */
|
||||
export function Any(options?: SchemaOptions): TAny {
|
||||
return CreateType({ [Kind]: 'Any' }, options) as never
|
||||
}
|
||||
29
src/type/any/index.ts
Normal file
29
src/type/any/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './any'
|
||||
41
src/type/argument/argument.ts
Normal file
41
src/type/argument/argument.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import type { TSchema } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
export interface TArgument<Index extends number = number> extends TSchema {
|
||||
[Kind]: 'Argument'
|
||||
static: unknown
|
||||
index: Index
|
||||
}
|
||||
/** `[JavaScript]` Creates an Argument Type. */
|
||||
export function Argument<Index extends number>(index: Index): TArgument<Index> {
|
||||
return CreateType({ [Kind]: 'Argument', index }) as never
|
||||
}
|
||||
29
src/type/argument/index.ts
Normal file
29
src/type/argument/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './argument'
|
||||
59
src/type/array/array.ts
Normal file
59
src/type/array/array.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import { Ensure } from '../helpers/index'
|
||||
import type { SchemaOptions, TSchema } from '../schema/index'
|
||||
import type { Static } from '../static/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
export interface ArrayOptions extends SchemaOptions {
|
||||
/** The minimum number of items in this array */
|
||||
minItems?: number
|
||||
/** The maximum number of items in this array */
|
||||
maxItems?: number
|
||||
/** Should this schema contain unique items */
|
||||
uniqueItems?: boolean
|
||||
/** A schema for which some elements should match */
|
||||
contains?: TSchema
|
||||
/** A minimum number of contains schema matches */
|
||||
minContains?: number
|
||||
/** A maximum number of contains schema matches */
|
||||
maxContains?: number
|
||||
}
|
||||
type ArrayStatic<T extends TSchema, P extends unknown[]> = Ensure<Static<T, P>[]>
|
||||
export interface TArray<T extends TSchema = TSchema> extends TSchema, ArrayOptions {
|
||||
[Kind]: 'Array'
|
||||
static: ArrayStatic<T, this['params']>
|
||||
type: 'array'
|
||||
items: T
|
||||
}
|
||||
/** `[Json]` Creates an Array type */
|
||||
export function Array<Type extends TSchema>(items: Type, options?: ArrayOptions): TArray<Type> {
|
||||
return CreateType({ [Kind]: 'Array', type: 'array', items }, options) as never
|
||||
}
|
||||
29
src/type/array/index.ts
Normal file
29
src/type/array/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './array'
|
||||
43
src/type/async-iterator/async-iterator.ts
Normal file
43
src/type/async-iterator/async-iterator.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Static } from '../static/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
import { CreateType } from '../create/type'
|
||||
|
||||
export interface TAsyncIterator<T extends TSchema = TSchema> extends TSchema {
|
||||
[Kind]: 'AsyncIterator'
|
||||
static: AsyncIterableIterator<Static<T, this['params']>>
|
||||
type: 'AsyncIterator'
|
||||
items: T
|
||||
}
|
||||
/** `[JavaScript]` Creates a AsyncIterator type */
|
||||
export function AsyncIterator<T extends TSchema>(items: T, options?: SchemaOptions): TAsyncIterator<T> {
|
||||
return CreateType({ [Kind]: 'AsyncIterator', type: 'AsyncIterator', items }, options) as never
|
||||
}
|
||||
29
src/type/async-iterator/index.ts
Normal file
29
src/type/async-iterator/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './async-iterator'
|
||||
121
src/type/awaited/awaited.ts
Normal file
121
src/type/awaited/awaited.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import { Ensure } from '../helpers/index'
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Computed, type TComputed } from '../computed/index'
|
||||
import { Intersect, type TIntersect } from '../intersect/index'
|
||||
import { Union, type TUnion } from '../union/index'
|
||||
import { type TPromise } from '../promise/index'
|
||||
import { Ref, type TRef } from '../ref/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsIntersect, IsUnion, IsPromise, IsRef, IsComputed } from '../guard/kind'
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// FromComputed
|
||||
// ----------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromComputed<Target extends string, Parameters extends TSchema[]> = Ensure<(
|
||||
TComputed<'Awaited', [TComputed<Target, Parameters>]>
|
||||
)>
|
||||
// prettier-ignore
|
||||
function FromComputed<Target extends string, Parameters extends TSchema[]>(target: Target, parameters: Parameters): TFromComputed<Target, Parameters> {
|
||||
return Computed('Awaited', [Computed(target, parameters)]) as never
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// Ref
|
||||
// ----------------------------------------------------------------
|
||||
type TFromRef<Ref extends string> = Ensure<TComputed<'Awaited', [TRef<Ref>]>>
|
||||
// prettier-ignore
|
||||
function FromRef<Ref extends string>($ref: Ref): TFromRef<Ref> {
|
||||
return Computed('Awaited', [Ref($ref)]) as never
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// FromIntersect
|
||||
// ----------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromIntersect<Types extends TSchema[]> = (
|
||||
TIntersect<TFromRest<Types>>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromIntersect<Types extends TSchema[]>(types: [...Types]): TFromIntersect<Types> {
|
||||
return Intersect(FromRest(types) as TSchema[]) as never
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// FromUnion
|
||||
// ----------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromUnion<Types extends TSchema[]> = TUnion<TFromRest<Types>>
|
||||
// prettier-ignore
|
||||
function FromUnion<Types extends TSchema[]>(types: [...Types]): TFromUnion<Types> {
|
||||
return Union(FromRest(types) as TSchema[]) as never
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// Promise
|
||||
// ----------------------------------------------------------------
|
||||
type TFromPromise<Type extends TSchema> = TAwaited<Type>
|
||||
// prettier-ignore
|
||||
function FromPromise<Type extends TSchema>(type: Type): TFromPromise<Type> {
|
||||
return Awaited(type) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromRest
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromRest<Types extends TSchema[], Result extends TSchema[] = []> = (
|
||||
Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]]
|
||||
? TFromRest<Right, [...Result, TAwaited<Left>]>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromRest<Types extends TSchema[]>(types: [...Types]) : TFromRest<Types> {
|
||||
return types.map(type => Awaited(type)) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TAwaited
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TAwaited<Type extends TSchema> = (
|
||||
Type extends TComputed<infer Target extends string, infer Parameters extends TSchema[]> ? TFromComputed<Target, Parameters> :
|
||||
Type extends TRef<infer Ref extends string> ? TFromRef<Ref> :
|
||||
Type extends TIntersect<infer Types extends TSchema[]> ? TIntersect<TFromRest<Types>> :
|
||||
Type extends TUnion<infer Types extends TSchema[]> ? TUnion<TFromRest<Types>> :
|
||||
Type extends TPromise<infer Type extends TSchema> ? TAwaited<Type> :
|
||||
Type
|
||||
)
|
||||
/** `[JavaScript]` Constructs a type by recursively unwrapping Promise types */
|
||||
export function Awaited<T extends TSchema>(type: T, options?: SchemaOptions): TAwaited<T> {
|
||||
return CreateType(
|
||||
IsComputed(type) ? FromComputed(type.target, type.parameters) : IsIntersect(type) ? FromIntersect(type.allOf) : IsUnion(type) ? FromUnion(type.anyOf) : IsPromise(type) ? FromPromise(type.item) : IsRef(type) ? FromRef(type.$ref) : type,
|
||||
options,
|
||||
) as never
|
||||
}
|
||||
29
src/type/awaited/index.ts
Normal file
29
src/type/awaited/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './awaited'
|
||||
48
src/type/bigint/bigint.ts
Normal file
48
src/type/bigint/bigint.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
import { CreateType } from '../create/index'
|
||||
|
||||
export interface BigIntOptions extends SchemaOptions {
|
||||
exclusiveMaximum?: bigint
|
||||
exclusiveMinimum?: bigint
|
||||
maximum?: bigint
|
||||
minimum?: bigint
|
||||
multipleOf?: bigint
|
||||
}
|
||||
export interface TBigInt extends TSchema, BigIntOptions {
|
||||
[Kind]: 'BigInt'
|
||||
static: bigint
|
||||
type: 'bigint'
|
||||
}
|
||||
/** `[JavaScript]` Creates a BigInt type */
|
||||
export function BigInt(options?: BigIntOptions): TBigInt {
|
||||
return CreateType({ [Kind]: 'BigInt', type: 'bigint' }, options) as never
|
||||
}
|
||||
29
src/type/bigint/index.ts
Normal file
29
src/type/bigint/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './bigint'
|
||||
41
src/type/boolean/boolean.ts
Normal file
41
src/type/boolean/boolean.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
import { CreateType } from '../create/index'
|
||||
|
||||
export interface TBoolean extends TSchema {
|
||||
[Kind]: 'Boolean'
|
||||
static: boolean
|
||||
type: 'boolean'
|
||||
}
|
||||
/** `[Json]` Creates a Boolean type */
|
||||
export function Boolean(options?: SchemaOptions): TBoolean {
|
||||
return CreateType({ [Kind]: 'Boolean', type: 'boolean' }, options) as never
|
||||
}
|
||||
29
src/type/boolean/index.ts
Normal file
29
src/type/boolean/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './boolean'
|
||||
30
src/type/clone/index.ts
Normal file
30
src/type/clone/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './type'
|
||||
export * from './value'
|
||||
39
src/type/clone/type.ts
Normal file
39
src/type/clone/type.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Clone } from './value'
|
||||
|
||||
/** Clones a Rest */
|
||||
export function CloneRest<T extends TSchema[]>(schemas: T): T {
|
||||
return schemas.map((schema) => CloneType(schema)) as never
|
||||
}
|
||||
/** Clones a Type */
|
||||
export function CloneType<T extends TSchema>(schema: T, options?: SchemaOptions): T {
|
||||
return options === undefined ? Clone(schema) : Clone({ ...options, ...schema })
|
||||
}
|
||||
67
src/type/clone/value.ts
Normal file
67
src/type/clone/value.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import * as ValueGuard from '../guard/value'
|
||||
|
||||
function ArrayType(value: unknown[]) {
|
||||
return (value as any).map((value: unknown) => Visit(value as any))
|
||||
}
|
||||
function DateType(value: Date) {
|
||||
return new Date(value.getTime())
|
||||
}
|
||||
function Uint8ArrayType(value: Uint8Array) {
|
||||
return new Uint8Array(value)
|
||||
}
|
||||
function RegExpType(value: RegExp) {
|
||||
return new RegExp(value.source, value.flags)
|
||||
}
|
||||
function ObjectType(value: Record<keyof any, unknown>) {
|
||||
const result = {} as Record<PropertyKey, unknown>
|
||||
for (const key of Object.getOwnPropertyNames(value)) {
|
||||
result[key] = Visit(value[key])
|
||||
}
|
||||
for (const key of Object.getOwnPropertySymbols(value)) {
|
||||
result[key] = Visit(value[key])
|
||||
}
|
||||
return result
|
||||
}
|
||||
// prettier-ignore
|
||||
function Visit(value: unknown): any {
|
||||
return (
|
||||
ValueGuard.IsArray(value) ? ArrayType(value) :
|
||||
ValueGuard.IsDate(value) ? DateType(value) :
|
||||
ValueGuard.IsUint8Array(value) ? Uint8ArrayType(value) :
|
||||
ValueGuard.IsRegExp(value) ? RegExpType(value) :
|
||||
ValueGuard.IsObject(value) ? ObjectType(value) :
|
||||
value
|
||||
)
|
||||
}
|
||||
/** Clones a value */
|
||||
export function Clone<T>(value: T): T {
|
||||
return Visit(value)
|
||||
}
|
||||
122
src/type/composite/composite.ts
Normal file
122
src/type/composite/composite.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema } from '../schema/index'
|
||||
import type { Evaluate } from '../helpers/index'
|
||||
import { IntersectEvaluated, type TIntersectEvaluated } from '../intersect/index'
|
||||
import { IndexFromPropertyKeys, type TIndexFromPropertyKeys } from '../indexed/index'
|
||||
import { KeyOfPropertyKeys, type TKeyOfPropertyKeys } from '../keyof/index'
|
||||
import { type TNever } from '../never/index'
|
||||
import { Object, type TObject, type TProperties, type ObjectOptions } from '../object/index'
|
||||
import { SetDistinct, TSetDistinct } from '../sets/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsNever } from '../guard/kind'
|
||||
// ------------------------------------------------------------------
|
||||
// CompositeKeys
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TCompositeKeys<T extends TSchema[], Acc extends PropertyKey[] = []> = (
|
||||
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
|
||||
? TCompositeKeys<R, [...Acc, ...TKeyOfPropertyKeys<L>]>
|
||||
: TSetDistinct<Acc>
|
||||
)
|
||||
// prettier-ignore
|
||||
function CompositeKeys<T extends TSchema[]>(T: [...T]): TCompositeKeys<T> {
|
||||
const Acc = [] as PropertyKey[]
|
||||
for(const L of T) Acc.push(...KeyOfPropertyKeys(L))
|
||||
return SetDistinct(Acc) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FilterNever
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFilterNever<T extends TSchema[], Acc extends TSchema[] = []> = (
|
||||
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
|
||||
? L extends TNever
|
||||
? TFilterNever<R, [...Acc]>
|
||||
: TFilterNever<R, [...Acc, L]>
|
||||
: Acc
|
||||
)
|
||||
// prettier-ignore
|
||||
function FilterNever<T extends TSchema[]>(T: [...T]): TFilterNever<T> {
|
||||
return T.filter(L => !IsNever(L)) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// CompositeProperty
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TCompositeProperty<T extends TSchema[], K extends PropertyKey, Acc extends TSchema[] = []> = (
|
||||
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
|
||||
? TCompositeProperty<R, K, [...Acc, ...TIndexFromPropertyKeys<L, [K]>]>
|
||||
: TFilterNever<Acc>
|
||||
)
|
||||
// prettier-ignore
|
||||
function CompositeProperty<T extends TSchema[], K extends PropertyKey>(T: [...T], K: K): TCompositeProperty<T, K> {
|
||||
const Acc = [] as TSchema[]
|
||||
for(const L of T) Acc.push(...IndexFromPropertyKeys(L, [K]))
|
||||
return FilterNever(Acc) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// CompositeProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TCompositeProperties<T extends TSchema[], K extends PropertyKey[], Acc = {}> = (
|
||||
K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]]
|
||||
? TCompositeProperties<T, R, Acc & { [_ in L]: TIntersectEvaluated<TCompositeProperty<T, L>> }>
|
||||
: Acc
|
||||
)
|
||||
// prettier-ignore
|
||||
function CompositeProperties<T extends TSchema[], K extends PropertyKey[] = []>(T: [...T], K: [...K]): TCompositeProperties<T, K> {
|
||||
const Acc = {} as never
|
||||
for(const L of K) {
|
||||
Acc[L] = IntersectEvaluated(CompositeProperty(T, L))
|
||||
}
|
||||
return Acc
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Composite
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TCompositeEvaluate<
|
||||
T extends TSchema[],
|
||||
K extends PropertyKey[] = TCompositeKeys<T>,
|
||||
P extends TProperties = Evaluate<TCompositeProperties<T, K>>,
|
||||
R extends TSchema = TObject<P>
|
||||
> = R
|
||||
// prettier-ignore
|
||||
export type TComposite<T extends TSchema[]> = TCompositeEvaluate<T>
|
||||
// prettier-ignore
|
||||
export function Composite<T extends TSchema[]>(T: [...T], options?: ObjectOptions): TComposite<T> {
|
||||
const K = CompositeKeys(T)
|
||||
const P = CompositeProperties(T, K)
|
||||
const R = Object(P, options)
|
||||
return R as never
|
||||
}
|
||||
29
src/type/composite/index.ts
Normal file
29
src/type/composite/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './composite'
|
||||
44
src/type/computed/computed.ts
Normal file
44
src/type/computed/computed.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { CreateType } from '../create/index'
|
||||
import { Kind } from '../symbols/symbols'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Computed
|
||||
// ------------------------------------------------------------------
|
||||
export interface TComputed<Target extends string = string, Parameters extends TSchema[] = []> extends TSchema {
|
||||
[Kind]: 'Computed'
|
||||
target: Target
|
||||
parameters: Parameters
|
||||
}
|
||||
/** `[Internal]` Creates a deferred computed type. This type is used exclusively in modules to defer resolution of computable types that contain interior references */
|
||||
export function Computed<Target extends string, Parameters extends TSchema[]>(target: Target, parameters: [...Parameters], options?: SchemaOptions): TComputed<Target, Parameters> {
|
||||
return CreateType({ [Kind]: 'Computed', target, parameters }, options) as never
|
||||
}
|
||||
29
src/type/computed/index.ts
Normal file
29
src/type/computed/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './computed'
|
||||
135
src/type/const/const.ts
Normal file
135
src/type/const/const.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { AssertRest, Evaluate } from '../helpers/index'
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
|
||||
import { Any, type TAny } from '../any/index'
|
||||
import { BigInt, type TBigInt } from '../bigint/index'
|
||||
import { Date, type TDate } from '../date/index'
|
||||
import { Function as FunctionType, type TFunction } from '../function/index'
|
||||
import { Literal, type TLiteral } from '../literal/index'
|
||||
import { type TNever } from '../never/index'
|
||||
import { Null, type TNull } from '../null/index'
|
||||
import { Object, type TObject } from '../object/index'
|
||||
import { Symbol, type TSymbol } from '../symbol/index'
|
||||
import { Tuple, type TTuple } from '../tuple/index'
|
||||
import { Readonly, type TReadonly } from '../readonly/index'
|
||||
import { Undefined, type TUndefined } from '../undefined/index'
|
||||
import { Uint8Array, type TUint8Array } from '../uint8array/index'
|
||||
import { Unknown, type TUnknown } from '../unknown/index'
|
||||
import { CreateType } from '../create/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ValueGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsArray, IsNumber, IsBigInt, IsUint8Array, IsDate, IsIterator, IsObject, IsAsyncIterator, IsFunction, IsUndefined, IsNull, IsSymbol, IsBoolean, IsString } from '../guard/value'
|
||||
// ------------------------------------------------------------------
|
||||
// FromArray
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromArray<T extends readonly unknown[]> =
|
||||
T extends readonly [infer L extends unknown, ...infer R extends unknown[]]
|
||||
? [FromValue<L, false>, ...TFromArray<R>]
|
||||
: T
|
||||
// prettier-ignore
|
||||
function FromArray<T extends readonly unknown[]>(T: [...T]): TFromArray<T> {
|
||||
return T.map(L => FromValue(L, false)) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperties<T extends Record<PropertyKey, unknown>> = {
|
||||
-readonly [K in keyof T]: FromValue<T[K], false> extends infer R extends TSchema
|
||||
? TReadonly<R>
|
||||
: TReadonly<TNever>
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromProperties<T extends Record<PropertyKey, unknown>>(value: T): 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
|
||||
// ------------------------------------------------------------------
|
||||
type TConditionalReadonly<T extends TSchema, Root extends boolean> = Root extends true ? T : TReadonly<T>
|
||||
function ConditionalReadonly<T extends TSchema, Root extends boolean>(T: T, root: Root): TConditionalReadonly<T, Root> {
|
||||
return (root === true ? T : Readonly(T)) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromValue
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type FromValue<T, Root extends boolean> =
|
||||
T extends AsyncIterableIterator<unknown> ? TConditionalReadonly<TAny, Root> :
|
||||
T extends IterableIterator<unknown> ? TConditionalReadonly<TAny, Root> :
|
||||
T extends readonly unknown[] ? TReadonly<TTuple<AssertRest<TFromArray<T>>>> :
|
||||
T extends Uint8Array ? TUint8Array :
|
||||
T extends Date ? TDate :
|
||||
T extends Record<PropertyKey, unknown> ? TConditionalReadonly<TObject<Evaluate<TFromProperties<T>>>, Root> :
|
||||
T extends Function ? TConditionalReadonly<TFunction<[], TUnknown>, Root> :
|
||||
T extends undefined ? TUndefined :
|
||||
T extends null ? TNull :
|
||||
T extends symbol ? TSymbol :
|
||||
T extends number ? TLiteral<T> :
|
||||
T extends boolean ? TLiteral<T> :
|
||||
T extends string ? TLiteral<T> :
|
||||
T extends bigint ? TBigInt :
|
||||
TObject<{}>
|
||||
// prettier-ignore
|
||||
function FromValue<T, Root extends boolean>(value: T, root: Root): FromValue<T, Root> {
|
||||
return (
|
||||
IsAsyncIterator(value) ? ConditionalReadonly(Any(), root) :
|
||||
IsIterator(value) ? ConditionalReadonly(Any(), root) :
|
||||
IsArray(value) ? Readonly(Tuple(FromArray(value) as TSchema[])) :
|
||||
IsUint8Array(value) ? Uint8Array() :
|
||||
IsDate(value) ? Date() :
|
||||
IsObject(value) ? ConditionalReadonly(Object(FromProperties(value as Record<PropertyKey, unknown>) as TProperties), root) :
|
||||
IsFunction(value) ? ConditionalReadonly(FunctionType([], Unknown()), root) :
|
||||
IsUndefined(value) ? Undefined() :
|
||||
IsNull(value) ? Null() :
|
||||
IsSymbol(value) ? Symbol() :
|
||||
IsBigInt(value) ? BigInt() :
|
||||
IsNumber(value) ? Literal(value) :
|
||||
IsBoolean(value) ? Literal(value) :
|
||||
IsString(value) ? Literal(value) :
|
||||
Object({})
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TConst
|
||||
// ------------------------------------------------------------------
|
||||
export type TConst<T> = FromValue<T, true>
|
||||
|
||||
/** `[JavaScript]` Creates a readonly const type from the given value. */
|
||||
export function Const</* const (not supported in 4.0) */ T>(T: T, options?: SchemaOptions): TConst<T> {
|
||||
return CreateType(FromValue(T, true), options) as never
|
||||
}
|
||||
29
src/type/const/index.ts
Normal file
29
src/type/const/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './const'
|
||||
47
src/type/constructor-parameters/constructor-parameters.ts
Normal file
47
src/type/constructor-parameters/constructor-parameters.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { TConstructor } from '../constructor/index'
|
||||
import { Tuple, type TTuple } from '../tuple/index'
|
||||
import { Never, type TNever } from '../never/index'
|
||||
import * as KindGuard from '../guard/kind'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ConstructorParameters
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TConstructorParameters<Type extends TSchema> = (
|
||||
Type extends TConstructor<infer Parameters extends TSchema[], infer _InstanceType extends TSchema>
|
||||
? TTuple<Parameters>
|
||||
: TNever
|
||||
)
|
||||
/** `[JavaScript]` Extracts the ConstructorParameters from the given Constructor type */
|
||||
export function ConstructorParameters<Type extends TSchema>(schema: Type, options?: SchemaOptions): TConstructorParameters<Type> {
|
||||
return (KindGuard.IsConstructor(schema) ? Tuple(schema.parameters, options) : Never(options)) as never
|
||||
}
|
||||
29
src/type/constructor-parameters/index.ts
Normal file
29
src/type/constructor-parameters/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './constructor-parameters'
|
||||
70
src/type/constructor/constructor.ts
Normal file
70
src/type/constructor/constructor.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Static } from '../static/index'
|
||||
import type { Ensure } from '../helpers/index'
|
||||
import type { TReadonlyOptional } from '../readonly-optional/index'
|
||||
import type { TReadonly } from '../readonly/index'
|
||||
import type { TOptional } from '../optional/index'
|
||||
import { CreateType } from '../create/type'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// StaticConstructor
|
||||
// ------------------------------------------------------------------
|
||||
type StaticReturnType<U extends TSchema, P extends unknown[]> = Static<U, P>
|
||||
// prettier-ignore
|
||||
type StaticParameter<T extends TSchema, P extends unknown[]> =
|
||||
T extends TReadonlyOptional<T> ? [Readonly<Static<T, P>>?] :
|
||||
T extends TReadonly<T> ? [Readonly<Static<T, P>>] :
|
||||
T extends TOptional<T> ? [Static<T, P>?] :
|
||||
[Static<T, P>]
|
||||
// prettier-ignore
|
||||
type StaticParameters<T extends TSchema[], P extends unknown[], Acc extends unknown[] = []> = (
|
||||
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
|
||||
? StaticParameters<R, P, [...Acc, ...StaticParameter<L, P>]>
|
||||
: Acc
|
||||
)
|
||||
// prettier-ignore
|
||||
type StaticConstructor<T extends TSchema[], U extends TSchema, P extends unknown[]> =
|
||||
Ensure<new (...param: StaticParameters<T, P>) => StaticReturnType<U, P>>
|
||||
// ------------------------------------------------------------------
|
||||
// TConstructor
|
||||
// ------------------------------------------------------------------
|
||||
export interface TConstructor<T extends TSchema[] = TSchema[], U extends TSchema = TSchema> extends TSchema {
|
||||
[Kind]: 'Constructor'
|
||||
static: StaticConstructor<T, U, this['params']>
|
||||
type: 'Constructor'
|
||||
parameters: T
|
||||
returns: U
|
||||
}
|
||||
/** `[JavaScript]` Creates a Constructor type */
|
||||
export function Constructor<T extends TSchema[], U extends TSchema>(parameters: [...T], returns: U, options?: SchemaOptions): TConstructor<T, U> {
|
||||
return CreateType({ [Kind]: 'Constructor', type: 'Constructor', parameters, returns }, options) as never
|
||||
}
|
||||
29
src/type/constructor/index.ts
Normal file
29
src/type/constructor/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './constructor'
|
||||
65
src/type/create/immutable.ts
Normal file
65
src/type/create/immutable.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import * as ValueGuard from '../guard/value'
|
||||
|
||||
function ImmutableArray(value: unknown[]) {
|
||||
return globalThis.Object.freeze(value as any).map((value: unknown) => Immutable(value as any))
|
||||
}
|
||||
function ImmutableDate(value: Date) {
|
||||
return value
|
||||
}
|
||||
function ImmutableUint8Array(value: Uint8Array) {
|
||||
return value
|
||||
}
|
||||
function ImmutableRegExp(value: RegExp) {
|
||||
return value
|
||||
}
|
||||
function ImmutableObject(value: Record<keyof any, unknown>) {
|
||||
const result = {} as Record<PropertyKey, unknown>
|
||||
for (const key of Object.getOwnPropertyNames(value)) {
|
||||
result[key] = Immutable(value[key])
|
||||
}
|
||||
for (const key of Object.getOwnPropertySymbols(value)) {
|
||||
result[key] = Immutable(value[key])
|
||||
}
|
||||
return globalThis.Object.freeze(result)
|
||||
}
|
||||
|
||||
/** Specialized deep immutable value. Applies freeze recursively to the given value */
|
||||
// prettier-ignore
|
||||
export function Immutable(value: unknown): unknown {
|
||||
return (
|
||||
ValueGuard.IsArray(value) ? ImmutableArray(value) :
|
||||
ValueGuard.IsDate(value) ? ImmutableDate(value) :
|
||||
ValueGuard.IsUint8Array(value) ? ImmutableUint8Array(value) :
|
||||
ValueGuard.IsRegExp(value) ? ImmutableRegExp(value) :
|
||||
ValueGuard.IsObject(value) ? ImmutableObject(value) :
|
||||
value
|
||||
)
|
||||
}
|
||||
29
src/type/create/index.ts
Normal file
29
src/type/create/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './type'
|
||||
45
src/type/create/type.ts
Normal file
45
src/type/create/type.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { TypeSystemPolicy } from '../../system/policy'
|
||||
import { SchemaOptions } from '../schema/schema'
|
||||
import { Immutable } from './immutable'
|
||||
import { Clone } from '../clone/value'
|
||||
|
||||
/** Creates TypeBox schematics using the configured InstanceMode */
|
||||
export function CreateType(schema: Record<any, unknown>, options?: SchemaOptions): unknown {
|
||||
const result = options !== undefined ? { ...options, ...schema } : schema
|
||||
switch (TypeSystemPolicy.InstanceMode) {
|
||||
case 'freeze':
|
||||
return Immutable(result)
|
||||
case 'clone':
|
||||
return Clone(result)
|
||||
default:
|
||||
return result
|
||||
}
|
||||
}
|
||||
53
src/type/date/date.ts
Normal file
53
src/type/date/date.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
import { CreateType } from '../create/type'
|
||||
|
||||
export interface DateOptions extends SchemaOptions {
|
||||
/** The exclusive maximum timestamp value */
|
||||
exclusiveMaximumTimestamp?: number
|
||||
/** The exclusive minimum timestamp value */
|
||||
exclusiveMinimumTimestamp?: number
|
||||
/** The maximum timestamp value */
|
||||
maximumTimestamp?: number
|
||||
/** The minimum timestamp value */
|
||||
minimumTimestamp?: number
|
||||
/** The multiple of timestamp value */
|
||||
multipleOfTimestamp?: number
|
||||
}
|
||||
export interface TDate extends TSchema, DateOptions {
|
||||
[Kind]: 'Date'
|
||||
static: Date
|
||||
type: 'date'
|
||||
}
|
||||
/** `[JavaScript]` Creates a Date type */
|
||||
export function Date(options?: DateOptions): TDate {
|
||||
return CreateType({ [Kind]: 'Date', type: 'Date' }, options) as never
|
||||
}
|
||||
29
src/type/date/index.ts
Normal file
29
src/type/date/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './date'
|
||||
36
src/type/discard/discard.ts
Normal file
36
src/type/discard/discard.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
function DiscardKey(value: Record<PropertyKey, any>, key: PropertyKey) {
|
||||
const { [key]: _, ...rest } = value
|
||||
return rest
|
||||
}
|
||||
/** Discards property keys from the given value. This function returns a shallow Clone. */
|
||||
export function Discard(value: Record<PropertyKey, any>, keys: PropertyKey[]) {
|
||||
return keys.reduce((acc, key) => DiscardKey(acc, key), value)
|
||||
}
|
||||
29
src/type/discard/index.ts
Normal file
29
src/type/discard/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './discard'
|
||||
58
src/type/enum/enum.ts
Normal file
58
src/type/enum/enum.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Literal, type TLiteral } from '../literal/index'
|
||||
import { Kind, Hint } from '../symbols/index'
|
||||
import { Union } from '../union/index'
|
||||
// ------------------------------------------------------------------
|
||||
// ValueGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsUndefined } from '../guard/value'
|
||||
// ------------------------------------------------------------------
|
||||
// TEnum
|
||||
// ------------------------------------------------------------------
|
||||
export type TEnumRecord = Record<TEnumKey, TEnumValue>
|
||||
export type TEnumValue = string | number
|
||||
export type TEnumKey = string
|
||||
export interface TEnum<T extends Record<string, string | number> = Record<string, string | number>> extends TSchema {
|
||||
[Kind]: 'Union'
|
||||
[Hint]: 'Enum'
|
||||
static: T[keyof T]
|
||||
anyOf: TLiteral<T[keyof T]>[]
|
||||
}
|
||||
/** `[Json]` Creates a Enum type */
|
||||
export function Enum<V extends TEnumValue, T extends Record<TEnumKey, V>>(item: T, options?: SchemaOptions): TEnum<T> {
|
||||
if (IsUndefined(item)) throw new Error('Enum undefined or empty')
|
||||
const values1 = globalThis.Object.getOwnPropertyNames(item)
|
||||
.filter((key) => isNaN(key as any))
|
||||
.map((key) => item[key]) as T[keyof T][]
|
||||
const values2 = [...new Set(values1)]
|
||||
const anyOf = values2.map((value) => Literal(value))
|
||||
return Union(anyOf, { ...options, [Hint]: 'Enum' }) as never
|
||||
}
|
||||
29
src/type/enum/index.ts
Normal file
29
src/type/enum/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './enum'
|
||||
34
src/type/error/error.ts
Normal file
34
src/type/error/error.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** The base Error type thrown for all TypeBox exceptions */
|
||||
export class TypeBoxError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
29
src/type/error/index.ts
Normal file
29
src/type/error/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './error'
|
||||
89
src/type/exclude/exclude-from-mapped-result.ts
Normal file
89
src/type/exclude/exclude-from-mapped-result.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import { MappedResult, type TMappedResult } from '../mapped/index'
|
||||
import { Exclude, type TExclude } from './exclude'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperties<
|
||||
K extends TProperties,
|
||||
T extends TSchema
|
||||
> = (
|
||||
{ [K2 in keyof K]: TExclude<K[K2], T> }
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromProperties<
|
||||
P extends TProperties,
|
||||
T extends TSchema
|
||||
>(P: P, U: T): 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
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema
|
||||
> = (
|
||||
TFromProperties<R['properties'], T>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema
|
||||
>(R: R, T: T): TFromMappedResult<R, T> {
|
||||
return FromProperties(R.properties, T) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ExcludeFromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExcludeFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<R, T>
|
||||
> = (
|
||||
TMappedResult<P>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function ExcludeFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<R, T>
|
||||
>(R: R, T: T): TMappedResult<P> {
|
||||
const P = FromMappedResult(R, T)
|
||||
return MappedResult(P) as never
|
||||
}
|
||||
39
src/type/exclude/exclude-from-template-literal.ts
Normal file
39
src/type/exclude/exclude-from-template-literal.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema } from '../schema/index'
|
||||
import { TExclude, Exclude } from './exclude'
|
||||
import { TemplateLiteralToUnion, type TTemplateLiteral, type TTemplateLiteralToUnion } from '../template-literal/index'
|
||||
|
||||
// prettier-ignore
|
||||
export type TExcludeFromTemplateLiteral<L extends TTemplateLiteral, R extends TSchema> = (
|
||||
TExclude<TTemplateLiteralToUnion<L>, R>
|
||||
)
|
||||
export function ExcludeFromTemplateLiteral<L extends TTemplateLiteral, R extends TSchema>(L: L, R: R): TExcludeFromTemplateLiteral<L, R> {
|
||||
return Exclude(TemplateLiteralToUnion(L), R) as never
|
||||
}
|
||||
82
src/type/exclude/exclude.ts
Normal file
82
src/type/exclude/exclude.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { UnionToTuple, AssertRest, AssertType } from '../helpers/index'
|
||||
import type { TMappedResult } from '../mapped/index'
|
||||
import { type TTemplateLiteral } from '../template-literal/index'
|
||||
import { Union, type TUnion } from '../union/index'
|
||||
import { Never, type TNever } from '../never/index'
|
||||
import { type Static } from '../static/index'
|
||||
import { type TUnionEvaluated } from '../union/index'
|
||||
import { ExtendsCheck, ExtendsResult } from '../extends/index'
|
||||
import { ExcludeFromMappedResult, type TExcludeFromMappedResult } from './exclude-from-mapped-result'
|
||||
import { ExcludeFromTemplateLiteral, type TExcludeFromTemplateLiteral } from './exclude-from-template-literal'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsMappedResult, IsTemplateLiteral, IsUnion } from '../guard/kind'
|
||||
// ------------------------------------------------------------------
|
||||
// ExcludeRest
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TExcludeRest<L extends TSchema[], R extends TSchema> = AssertRest<UnionToTuple<{
|
||||
[K in keyof L]: Static<AssertType<L[K]>> extends Static<R> ? never : L[K]
|
||||
}[number]>> extends infer R extends TSchema[] ? TUnionEvaluated<R> : never
|
||||
|
||||
function ExcludeRest<L extends TSchema[], R extends TSchema>(L: [...L], R: R) {
|
||||
const excluded = L.filter((inner) => ExtendsCheck(inner, R) === ExtendsResult.False)
|
||||
return excluded.length === 1 ? excluded[0] : Union(excluded)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TExclude
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExclude<L extends TSchema, R extends TSchema> = (
|
||||
L extends TUnion<infer S> ? TExcludeRest<S, R> :
|
||||
L extends R ? TNever : L
|
||||
)
|
||||
/** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */
|
||||
export function Exclude<L extends TMappedResult, R extends TSchema>(unionType: L, excludedMembers: R, options?: SchemaOptions): TExcludeFromMappedResult<L, R>
|
||||
/** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */
|
||||
export function Exclude<L extends TTemplateLiteral, R extends TSchema>(unionType: L, excludedMembers: R, options?: SchemaOptions): TExcludeFromTemplateLiteral<L, R>
|
||||
/** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */
|
||||
export function Exclude<L extends TSchema, R extends TSchema>(unionType: L, excludedMembers: R, options?: SchemaOptions): TExclude<L, R>
|
||||
/** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */
|
||||
export function Exclude(L: TSchema, R: TSchema, options: SchemaOptions = {}): any {
|
||||
// overloads
|
||||
if (IsTemplateLiteral(L)) return CreateType(ExcludeFromTemplateLiteral(L, R), options)
|
||||
if (IsMappedResult(L)) return CreateType(ExcludeFromMappedResult(L, R), options)
|
||||
// prettier-ignore
|
||||
return CreateType(
|
||||
IsUnion(L) ? ExcludeRest(L.anyOf, R) :
|
||||
ExtendsCheck(L, R) !== ExtendsResult.False ? Never() : L
|
||||
, options)
|
||||
}
|
||||
31
src/type/exclude/index.ts
Normal file
31
src/type/exclude/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './exclude-from-mapped-result'
|
||||
export * from './exclude-from-template-literal'
|
||||
export * from './exclude'
|
||||
776
src/type/extends/extends-check.ts
Normal file
776
src/type/extends/extends-check.ts
Normal file
@@ -0,0 +1,776 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { type TAny, Any } from '../any/index'
|
||||
import { type TArray } from '../array/index'
|
||||
import { type TAsyncIterator } from '../async-iterator/index'
|
||||
import { type TBigInt } from '../bigint/index'
|
||||
import { type TBoolean } from '../boolean/index'
|
||||
import { type TConstructor } from '../constructor/index'
|
||||
import { type TDate } from '../date/index'
|
||||
import { type TFunction, Function as FunctionType } from '../function/index'
|
||||
import { type TInteger } from '../integer/index'
|
||||
import { type TIntersect } from '../intersect/index'
|
||||
import { type TIterator } from '../iterator/index'
|
||||
import { type TLiteral } from '../literal/index'
|
||||
import { type TNever } from '../never/index'
|
||||
import { type TNot } from '../not/index'
|
||||
import { type TNull } from '../null/index'
|
||||
import { type TNumber, Number } from '../number/index'
|
||||
import { type TObject } from '../object/index'
|
||||
import { type TPromise } from '../promise/index'
|
||||
import { type TRecord } from '../record/index'
|
||||
import { type TSchema } from '../schema/index'
|
||||
import { type TString, String } from '../string/index'
|
||||
import { type TSymbol } from '../symbol/index'
|
||||
import { type TTuple } from '../tuple/index'
|
||||
import { type TUint8Array } from '../uint8array/index'
|
||||
import { type TUndefined } from '../undefined/index'
|
||||
import { type TUnion } from '../union/index'
|
||||
import { type TUnknown, Unknown } from '../unknown/index'
|
||||
import { type TVoid } from '../void/index'
|
||||
|
||||
import { TemplateLiteralToUnion } from '../template-literal/index'
|
||||
import { PatternNumberExact, PatternStringExact } from '../patterns/index'
|
||||
import { Kind, Hint } from '../symbols/index'
|
||||
import { TypeBoxError } from '../error/index'
|
||||
import { TypeGuard, ValueGuard } from '../guard/index'
|
||||
|
||||
export class ExtendsResolverError extends TypeBoxError {}
|
||||
|
||||
export enum ExtendsResult {
|
||||
Union,
|
||||
True,
|
||||
False,
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// IntoBooleanResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function IntoBooleanResult(result: ExtendsResult) {
|
||||
return result === ExtendsResult.False ? result : ExtendsResult.True
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Throw
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function Throw(message: string): never {
|
||||
throw new ExtendsResolverError(message)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// StructuralRight
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function IsStructuralRight(right: TSchema): boolean {
|
||||
return (
|
||||
TypeGuard.IsNever(right) ||
|
||||
TypeGuard.IsIntersect(right) ||
|
||||
TypeGuard.IsUnion(right) ||
|
||||
TypeGuard.IsUnknown(right) ||
|
||||
TypeGuard.IsAny(right)
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function StructuralRight(left: TSchema, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsNever(right) ? FromNeverRight(left, right) :
|
||||
TypeGuard.IsIntersect(right) ? FromIntersectRight(left, right) :
|
||||
TypeGuard.IsUnion(right) ? FromUnionRight(left, right) :
|
||||
TypeGuard.IsUnknown(right) ? FromUnknownRight(left, right) :
|
||||
TypeGuard.IsAny(right) ? FromAnyRight(left, right) :
|
||||
Throw('StructuralRight')
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Any
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromAnyRight(left: TSchema, right: TAny) {
|
||||
return ExtendsResult.True
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromAny(left: TAny, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsIntersect(right) ? FromIntersectRight(left, right) :
|
||||
(TypeGuard.IsUnion(right) && right.anyOf.some((schema) => TypeGuard.IsAny(schema) || TypeGuard.IsUnknown(schema))) ? ExtendsResult.True :
|
||||
TypeGuard.IsUnion(right) ? ExtendsResult.Union :
|
||||
TypeGuard.IsUnknown(right) ? ExtendsResult.True :
|
||||
TypeGuard.IsAny(right) ? ExtendsResult.True :
|
||||
ExtendsResult.Union
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Array
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromArrayRight(left: TSchema, right: TArray) {
|
||||
return (
|
||||
TypeGuard.IsUnknown(left) ? ExtendsResult.False :
|
||||
TypeGuard.IsAny(left) ? ExtendsResult.Union :
|
||||
TypeGuard.IsNever(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromArray(left: TArray, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsObject(right) && IsObjectArrayLike(right) ? ExtendsResult.True :
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
!TypeGuard.IsArray(right) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.items, right.items))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// AsyncIterator
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromAsyncIterator(left: TAsyncIterator, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
!TypeGuard.IsAsyncIterator(right) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.items, right.items))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// BigInt
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromBigInt(left: TBigInt, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsBigInt(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Boolean
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromBooleanRight(left: TSchema, right: TBoolean) {
|
||||
return (
|
||||
TypeGuard.IsLiteralBoolean(left) ? ExtendsResult.True :
|
||||
TypeGuard.IsBoolean(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromBoolean(left: TBoolean, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsBoolean(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromConstructor(left: TConstructor, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
!TypeGuard.IsConstructor(right) ? ExtendsResult.False :
|
||||
left.parameters.length > right.parameters.length ? ExtendsResult.False :
|
||||
(!left.parameters.every((schema, index) => IntoBooleanResult(Visit(right.parameters[index], schema)) === ExtendsResult.True)) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.returns, right.returns))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Date
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromDate(left: TDate, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsDate(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Function
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromFunction(left: TFunction, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
!TypeGuard.IsFunction(right) ? ExtendsResult.False :
|
||||
left.parameters.length > right.parameters.length ? ExtendsResult.False :
|
||||
(!left.parameters.every((schema, index) => IntoBooleanResult(Visit(right.parameters[index], schema)) === ExtendsResult.True)) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.returns, right.returns))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Integer
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromIntegerRight(left: TSchema, right: TInteger) {
|
||||
return (
|
||||
TypeGuard.IsLiteral(left) && ValueGuard.IsNumber(left.const) ? ExtendsResult.True :
|
||||
TypeGuard.IsNumber(left) || TypeGuard.IsInteger(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromInteger(left: TInteger, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
TypeGuard.IsInteger(right) || TypeGuard.IsNumber(right) ? ExtendsResult.True :
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Intersect
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromIntersectRight(left: TSchema, right: TIntersect): ExtendsResult {
|
||||
return right.allOf.every((schema) => Visit(left, schema) === ExtendsResult.True)
|
||||
? ExtendsResult.True
|
||||
: ExtendsResult.False
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromIntersect(left: TIntersect, right: TSchema) {
|
||||
return left.allOf.some((schema) => Visit(schema, right) === ExtendsResult.True)
|
||||
? ExtendsResult.True
|
||||
: ExtendsResult.False
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Iterator
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromIterator(left: TIterator, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
!TypeGuard.IsIterator(right) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.items, right.items))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Literal
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromLiteral(left: TLiteral, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
TypeGuard.IsLiteral(right) && right.const === left.const ? ExtendsResult.True :
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsString(right) ? FromStringRight(left, right) :
|
||||
TypeGuard.IsNumber(right) ? FromNumberRight(left, right) :
|
||||
TypeGuard.IsInteger(right) ? FromIntegerRight(left, right) :
|
||||
TypeGuard.IsBoolean(right) ? FromBooleanRight(left, right) :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Never
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromNeverRight(left: TSchema, right: TNever) {
|
||||
return ExtendsResult.False
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromNever(left: TNever, right: TSchema) {
|
||||
return ExtendsResult.True
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Not
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function UnwrapTNot<T extends TNot>(schema: T): TUnknown | TNot['not'] {
|
||||
let [current, depth]: [TSchema, number] = [schema, 0]
|
||||
while (true) {
|
||||
if (!TypeGuard.IsNot(current)) break
|
||||
current = current.not
|
||||
depth += 1
|
||||
}
|
||||
return depth % 2 === 0 ? current : Unknown()
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromNot(left: TSchema, right: TSchema) {
|
||||
// TypeScript has no concept of negated types, and attempts to correctly check the negated
|
||||
// type at runtime would put TypeBox at odds with TypeScripts ability to statically infer
|
||||
// the type. Instead we unwrap to either unknown or T and continue evaluating.
|
||||
// prettier-ignore
|
||||
return (
|
||||
TypeGuard.IsNot(left) ? Visit(UnwrapTNot(left), right) :
|
||||
TypeGuard.IsNot(right) ? Visit(left, UnwrapTNot(right)) :
|
||||
Throw('Invalid fallthrough for Not')
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Null
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromNull(left: TNull, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsNull(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Number
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromNumberRight(left: TSchema, right: TNumber) {
|
||||
return (
|
||||
TypeGuard.IsLiteralNumber(left) ? ExtendsResult.True :
|
||||
TypeGuard.IsNumber(left) || TypeGuard.IsInteger(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromNumber(left: TNumber, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsInteger(right) || TypeGuard.IsNumber(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Object
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function IsObjectPropertyCount(schema: TObject, count: number) {
|
||||
return Object.getOwnPropertyNames(schema.properties).length === count
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectStringLike(schema: TObject) {
|
||||
return IsObjectArrayLike(schema)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectSymbolLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0) || (
|
||||
IsObjectPropertyCount(schema, 1) && 'description' in schema.properties && TypeGuard.IsUnion(schema.properties.description) && schema.properties.description.anyOf.length === 2 && ((
|
||||
TypeGuard.IsString(schema.properties.description.anyOf[0]) &&
|
||||
TypeGuard.IsUndefined(schema.properties.description.anyOf[1])
|
||||
) || (
|
||||
TypeGuard.IsString(schema.properties.description.anyOf[1]) &&
|
||||
TypeGuard.IsUndefined(schema.properties.description.anyOf[0])
|
||||
))
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectNumberLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectBooleanLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectBigIntLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectDateLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectUint8ArrayLike(schema: TObject) {
|
||||
return IsObjectArrayLike(schema)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectFunctionLike(schema: TObject) {
|
||||
const length = Number()
|
||||
return IsObjectPropertyCount(schema, 0) || (IsObjectPropertyCount(schema, 1) && 'length' in schema.properties && IntoBooleanResult(Visit(schema.properties['length'], length)) === ExtendsResult.True)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectConstructorLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectArrayLike(schema: TObject) {
|
||||
const length = Number()
|
||||
return IsObjectPropertyCount(schema, 0) || (IsObjectPropertyCount(schema, 1) && 'length' in schema.properties && IntoBooleanResult(Visit(schema.properties['length'], length)) === ExtendsResult.True)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectPromiseLike(schema: TObject) {
|
||||
const then = FunctionType([Any()], Any())
|
||||
return IsObjectPropertyCount(schema, 0) || (IsObjectPropertyCount(schema, 1) && 'then' in schema.properties && IntoBooleanResult(Visit(schema.properties['then'], then)) === ExtendsResult.True)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Property
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function Property(left: TSchema, right: TSchema) {
|
||||
return (
|
||||
Visit(left, right) === ExtendsResult.False ? ExtendsResult.False :
|
||||
TypeGuard.IsOptional(left) && !TypeGuard.IsOptional(right) ? ExtendsResult.False :
|
||||
ExtendsResult.True
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromObjectRight(left: TSchema, right: TObject) {
|
||||
return (
|
||||
TypeGuard.IsUnknown(left) ? ExtendsResult.False :
|
||||
TypeGuard.IsAny(left) ? ExtendsResult.Union : (
|
||||
TypeGuard.IsNever(left) ||
|
||||
(TypeGuard.IsLiteralString(left) && IsObjectStringLike(right)) ||
|
||||
(TypeGuard.IsLiteralNumber(left) && IsObjectNumberLike(right)) ||
|
||||
(TypeGuard.IsLiteralBoolean(left) && IsObjectBooleanLike(right)) ||
|
||||
(TypeGuard.IsSymbol(left) && IsObjectSymbolLike(right)) ||
|
||||
(TypeGuard.IsBigInt(left) && IsObjectBigIntLike(right)) ||
|
||||
(TypeGuard.IsString(left) && IsObjectStringLike(right)) ||
|
||||
(TypeGuard.IsSymbol(left) && IsObjectSymbolLike(right)) ||
|
||||
(TypeGuard.IsNumber(left) && IsObjectNumberLike(right)) ||
|
||||
(TypeGuard.IsInteger(left) && IsObjectNumberLike(right)) ||
|
||||
(TypeGuard.IsBoolean(left) && IsObjectBooleanLike(right)) ||
|
||||
(TypeGuard.IsUint8Array(left) && IsObjectUint8ArrayLike(right)) ||
|
||||
(TypeGuard.IsDate(left) && IsObjectDateLike(right)) ||
|
||||
(TypeGuard.IsConstructor(left) && IsObjectConstructorLike(right)) ||
|
||||
(TypeGuard.IsFunction(left) && IsObjectFunctionLike(right))
|
||||
) ? ExtendsResult.True :
|
||||
(TypeGuard.IsRecord(left) && TypeGuard.IsString(RecordKey(left))) ? (() => {
|
||||
// When expressing a Record with literal key values, the Record is converted into a Object with
|
||||
// the Hint assigned as `Record`. This is used to invert the extends logic.
|
||||
return right[Hint] === 'Record' ? ExtendsResult.True : ExtendsResult.False
|
||||
})() :
|
||||
(TypeGuard.IsRecord(left) && TypeGuard.IsNumber(RecordKey(left))) ? (() => {
|
||||
return IsObjectPropertyCount(right, 0) ? ExtendsResult.True : ExtendsResult.False
|
||||
})() :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromObject(left: TObject, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
!TypeGuard.IsObject(right) ? ExtendsResult.False :
|
||||
(() => {
|
||||
for (const key of Object.getOwnPropertyNames(right.properties)) {
|
||||
if (!(key in left.properties) && !TypeGuard.IsOptional(right.properties[key])) {
|
||||
return ExtendsResult.False
|
||||
}
|
||||
if (TypeGuard.IsOptional(right.properties[key])) {
|
||||
return ExtendsResult.True
|
||||
}
|
||||
if (Property(left.properties[key], right.properties[key]) === ExtendsResult.False) {
|
||||
return ExtendsResult.False
|
||||
}
|
||||
}
|
||||
return ExtendsResult.True
|
||||
})()
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Promise
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromPromise(left: TPromise, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) && IsObjectPromiseLike(right) ? ExtendsResult.True :
|
||||
!TypeGuard.IsPromise(right) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.item, right.item))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Record
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function RecordKey(schema: TRecord) {
|
||||
return (
|
||||
PatternNumberExact in schema.patternProperties ? Number() :
|
||||
PatternStringExact in schema.patternProperties ? String() :
|
||||
Throw('Unknown record key pattern')
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function RecordValue(schema: TRecord) {
|
||||
return (
|
||||
PatternNumberExact in schema.patternProperties ? schema.patternProperties[PatternNumberExact] :
|
||||
PatternStringExact in schema.patternProperties ? schema.patternProperties[PatternStringExact] :
|
||||
Throw('Unable to get record value schema')
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromRecordRight(left: TSchema, right: TRecord) {
|
||||
const [Key, Value] = [RecordKey(right), RecordValue(right)]
|
||||
return (
|
||||
(
|
||||
TypeGuard.IsLiteralString(left) && TypeGuard.IsNumber(Key) && IntoBooleanResult(Visit(left, Value)) === ExtendsResult.True) ? ExtendsResult.True :
|
||||
TypeGuard.IsUint8Array(left) && TypeGuard.IsNumber(Key) ? Visit(left, Value) :
|
||||
TypeGuard.IsString(left) && TypeGuard.IsNumber(Key) ? Visit(left, Value) :
|
||||
TypeGuard.IsArray(left) && TypeGuard.IsNumber(Key) ? Visit(left, Value) :
|
||||
TypeGuard.IsObject(left) ? (() => {
|
||||
for (const key of Object.getOwnPropertyNames(left.properties)) {
|
||||
if (Property(Value, left.properties[key]) === ExtendsResult.False) {
|
||||
return ExtendsResult.False
|
||||
}
|
||||
}
|
||||
return ExtendsResult.True
|
||||
})() :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromRecord(left: TRecord, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
!TypeGuard.IsRecord(right) ? ExtendsResult.False :
|
||||
Visit(RecordValue(left), RecordValue(right))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// RegExp
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromRegExp(left: TSchema, right: TSchema) {
|
||||
// Note: RegExp types evaluate as strings, not RegExp objects.
|
||||
// Here we remap either into string and continue evaluating.
|
||||
const L = TypeGuard.IsRegExp(left) ? String() : left
|
||||
const R = TypeGuard.IsRegExp(right) ? String() : right
|
||||
return Visit(L, R)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// String
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromStringRight(left: TSchema, right: TString) {
|
||||
return (
|
||||
TypeGuard.IsLiteral(left) && ValueGuard.IsString(left.const) ? ExtendsResult.True :
|
||||
TypeGuard.IsString(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromString(left: TString, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsString(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Symbol
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromSymbol(left: TSymbol, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsSymbol(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TemplateLiteral
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromTemplateLiteral(left: TSchema, right: TSchema) {
|
||||
// TemplateLiteral types are resolved to either unions for finite expressions or string
|
||||
// for infinite expressions. Here we call to TemplateLiteralResolver to resolve for
|
||||
// either type and continue evaluating.
|
||||
return (
|
||||
TypeGuard.IsTemplateLiteral(left) ? Visit(TemplateLiteralToUnion(left), right) :
|
||||
TypeGuard.IsTemplateLiteral(right) ? Visit(left, TemplateLiteralToUnion(right)) :
|
||||
Throw('Invalid fallthrough for TemplateLiteral')
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Tuple
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function IsArrayOfTuple(left: TTuple, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsArray(right) &&
|
||||
left.items !== undefined &&
|
||||
left.items.every((schema) => Visit(schema, right.items) === ExtendsResult.True)
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromTupleRight(left: TSchema, right: TTuple) {
|
||||
return (
|
||||
TypeGuard.IsNever(left) ? ExtendsResult.True :
|
||||
TypeGuard.IsUnknown(left) ? ExtendsResult.False :
|
||||
TypeGuard.IsAny(left) ? ExtendsResult.Union :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromTuple(left: TTuple, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) && IsObjectArrayLike(right) ? ExtendsResult.True :
|
||||
TypeGuard.IsArray(right) && IsArrayOfTuple(left, right) ? ExtendsResult.True :
|
||||
!TypeGuard.IsTuple(right) ? ExtendsResult.False :
|
||||
(ValueGuard.IsUndefined(left.items) && !ValueGuard.IsUndefined(right.items)) || (!ValueGuard.IsUndefined(left.items) && ValueGuard.IsUndefined(right.items)) ? ExtendsResult.False :
|
||||
(ValueGuard.IsUndefined(left.items) && !ValueGuard.IsUndefined(right.items)) ? ExtendsResult.True :
|
||||
left.items!.every((schema, index) => Visit(schema, right.items![index]) === ExtendsResult.True) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Uint8Array
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromUint8Array(left: TUint8Array, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsUint8Array(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Undefined
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromUndefined(left: TUndefined, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsVoid(right) ? FromVoidRight(left, right) :
|
||||
TypeGuard.IsUndefined(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Union
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromUnionRight(left: TSchema, right: TUnion): ExtendsResult {
|
||||
return right.anyOf.some((schema) => Visit(left, schema) === ExtendsResult.True)
|
||||
? ExtendsResult.True
|
||||
: ExtendsResult.False
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromUnion(left: TUnion, right: TSchema): ExtendsResult {
|
||||
return left.anyOf.every((schema) => Visit(schema, right) === ExtendsResult.True)
|
||||
? ExtendsResult.True
|
||||
: ExtendsResult.False
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Unknown
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromUnknownRight(left: TSchema, right: TUnknown) {
|
||||
return ExtendsResult.True
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromUnknown(left: TUnknown, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsNever(right) ? FromNeverRight(left, right) :
|
||||
TypeGuard.IsIntersect(right) ? FromIntersectRight(left, right) :
|
||||
TypeGuard.IsUnion(right) ? FromUnionRight(left, right) :
|
||||
TypeGuard.IsAny(right) ? FromAnyRight(left, right) :
|
||||
TypeGuard.IsString(right) ? FromStringRight(left, right) :
|
||||
TypeGuard.IsNumber(right) ? FromNumberRight(left, right) :
|
||||
TypeGuard.IsInteger(right) ? FromIntegerRight(left, right) :
|
||||
TypeGuard.IsBoolean(right) ? FromBooleanRight(left, right) :
|
||||
TypeGuard.IsArray(right) ? FromArrayRight(left, right) :
|
||||
TypeGuard.IsTuple(right) ? FromTupleRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsUnknown(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Void
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromVoidRight(left: TSchema, right: TVoid) {
|
||||
return (
|
||||
TypeGuard.IsUndefined(left) ? ExtendsResult.True :
|
||||
TypeGuard.IsUndefined(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromVoid(left: TVoid, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsIntersect(right) ? FromIntersectRight(left, right) :
|
||||
TypeGuard.IsUnion(right) ? FromUnionRight(left, right) :
|
||||
TypeGuard.IsUnknown(right) ? FromUnknownRight(left, right) :
|
||||
TypeGuard.IsAny(right) ? FromAnyRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsVoid(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function Visit(left: TSchema, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
// resolvable
|
||||
(TypeGuard.IsTemplateLiteral(left) || TypeGuard.IsTemplateLiteral(right)) ? FromTemplateLiteral(left, right) :
|
||||
(TypeGuard.IsRegExp(left) || TypeGuard.IsRegExp(right)) ? FromRegExp(left, right) :
|
||||
(TypeGuard.IsNot(left) || TypeGuard.IsNot(right)) ? FromNot(left, right) :
|
||||
// standard
|
||||
TypeGuard.IsAny(left) ? FromAny(left, right) :
|
||||
TypeGuard.IsArray(left) ? FromArray(left, right) :
|
||||
TypeGuard.IsBigInt(left) ? FromBigInt(left, right) :
|
||||
TypeGuard.IsBoolean(left) ? FromBoolean(left, right) :
|
||||
TypeGuard.IsAsyncIterator(left) ? FromAsyncIterator(left, right) :
|
||||
TypeGuard.IsConstructor(left) ? FromConstructor(left, right) :
|
||||
TypeGuard.IsDate(left) ? FromDate(left, right) :
|
||||
TypeGuard.IsFunction(left) ? FromFunction(left, right) :
|
||||
TypeGuard.IsInteger(left) ? FromInteger(left, right) :
|
||||
TypeGuard.IsIntersect(left) ? FromIntersect(left, right) :
|
||||
TypeGuard.IsIterator(left) ? FromIterator(left, right) :
|
||||
TypeGuard.IsLiteral(left) ? FromLiteral(left, right) :
|
||||
TypeGuard.IsNever(left) ? FromNever(left, right) :
|
||||
TypeGuard.IsNull(left) ? FromNull(left, right) :
|
||||
TypeGuard.IsNumber(left) ? FromNumber(left, right) :
|
||||
TypeGuard.IsObject(left) ? FromObject(left, right) :
|
||||
TypeGuard.IsRecord(left) ? FromRecord(left, right) :
|
||||
TypeGuard.IsString(left) ? FromString(left, right) :
|
||||
TypeGuard.IsSymbol(left) ? FromSymbol(left, right) :
|
||||
TypeGuard.IsTuple(left) ? FromTuple(left, right) :
|
||||
TypeGuard.IsPromise(left) ? FromPromise(left, right) :
|
||||
TypeGuard.IsUint8Array(left) ? FromUint8Array(left, right) :
|
||||
TypeGuard.IsUndefined(left) ? FromUndefined(left, right) :
|
||||
TypeGuard.IsUnion(left) ? FromUnion(left, right) :
|
||||
TypeGuard.IsUnknown(left) ? FromUnknown(left, right) :
|
||||
TypeGuard.IsVoid(left) ? FromVoid(left, right) :
|
||||
Throw(`Unknown left type operand '${left[Kind]}'`)
|
||||
)
|
||||
}
|
||||
export function ExtendsCheck(left: TSchema, right: TSchema): ExtendsResult {
|
||||
return Visit(left, right)
|
||||
}
|
||||
130
src/type/extends/extends-from-mapped-key.ts
Normal file
130
src/type/extends/extends-from-mapped-key.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import type { Assert } from '../helpers/index'
|
||||
import { MappedResult, type TMappedResult, type TMappedKey } from '../mapped/index'
|
||||
import { Literal, type TLiteral, type TLiteralValue } from '../literal/index'
|
||||
import { Extends, type TExtends } from './extends'
|
||||
import { Clone } from '../clone/value'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FromPropertyKey
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromPropertyKey<
|
||||
K extends PropertyKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema
|
||||
> = {
|
||||
[_ in K]: TExtends<TLiteral<Assert<K, TLiteralValue>>, U, L, R>
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromPropertyKey<
|
||||
K extends PropertyKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema
|
||||
>(K: K, U: U, L: L, R: R, options?: SchemaOptions): TFromPropertyKey<K, U, L, R> {
|
||||
return {
|
||||
[K]: Extends(Literal(K as TLiteralValue), U, L, R, Clone(options)) as any
|
||||
} as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromPropertyKeys
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromPropertyKeys<
|
||||
K extends PropertyKey[],
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema,
|
||||
Acc extends TProperties = {}
|
||||
> = (
|
||||
K extends [infer LK extends PropertyKey, ...infer RK extends PropertyKey[]]
|
||||
? TFromPropertyKeys<RK, U, L, R, Acc & TFromPropertyKey<LK, U, L, R>>
|
||||
: Acc
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromPropertyKeys<
|
||||
K extends PropertyKey[],
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema
|
||||
>(K: [...K], U: U, L: L, R: R, options?: SchemaOptions): TFromPropertyKeys<K, U, L, R> {
|
||||
return K.reduce((Acc, LK) => {
|
||||
return { ...Acc, ...FromPropertyKey(LK, U, L, R, options) }
|
||||
}, {} as TProperties) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromMappedKey
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromMappedKey<
|
||||
K extends TMappedKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema
|
||||
> = (
|
||||
TFromPropertyKeys<K['keys'], U, L, R>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromMappedKey<
|
||||
K extends TMappedKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema
|
||||
>(K: K, U: U, L: L, R: R, options?: SchemaOptions): TFromMappedKey<K, U, L, R> {
|
||||
return FromPropertyKeys(K.keys, U, L, R, options) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ExtendsFromMappedKey
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExtendsFromMappedKey<
|
||||
T extends TMappedKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema,
|
||||
P extends TProperties = TFromMappedKey<T, U, L, R>
|
||||
> = (
|
||||
TMappedResult<P>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function ExtendsFromMappedKey<
|
||||
T extends TMappedKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema,
|
||||
P extends TProperties = TFromMappedKey<T, U, L, R>
|
||||
>(T: T, U: U, L: L, R: R, options?: SchemaOptions): TMappedResult<P> {
|
||||
const P = FromMappedKey(T, U, L, R, options)
|
||||
return MappedResult(P) as never
|
||||
}
|
||||
102
src/type/extends/extends-from-mapped-result.ts
Normal file
102
src/type/extends/extends-from-mapped-result.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import { MappedResult, type TMappedResult } from '../mapped/index'
|
||||
import { Extends, type TExtends } from './extends'
|
||||
import { Clone } from '../clone/value'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperties<
|
||||
P extends TProperties,
|
||||
Right extends TSchema,
|
||||
False extends TSchema,
|
||||
True extends TSchema
|
||||
> = (
|
||||
{ [K2 in keyof P]: TExtends<P[K2], Right, False, True> }
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromProperties<
|
||||
P extends TProperties,
|
||||
Right extends TSchema,
|
||||
True extends TSchema,
|
||||
False extends TSchema
|
||||
>(P: P, Right: Right, True: True, False: False, options?: SchemaOptions): 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, Clone(options))
|
||||
return Acc as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromMappedResult<
|
||||
Left extends TMappedResult,
|
||||
Right extends TSchema,
|
||||
True extends TSchema,
|
||||
False extends TSchema
|
||||
> = (
|
||||
TFromProperties<Left['properties'], Right, True, False>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromMappedResult<
|
||||
Left extends TMappedResult,
|
||||
Right extends TSchema,
|
||||
True extends TSchema,
|
||||
False extends TSchema
|
||||
>(Left: Left, Right: Right, True: True, False: False, options?: SchemaOptions): TFromMappedResult<Left, Right, True, False> {
|
||||
return FromProperties(Left.properties, Right, True, False, options) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ExtendsFromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExtendsFromMappedResult<
|
||||
Left extends TMappedResult,
|
||||
Right extends TSchema,
|
||||
True extends TSchema,
|
||||
False extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<Left, Right, True, False>
|
||||
> = (
|
||||
TMappedResult<P>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function ExtendsFromMappedResult<
|
||||
Left extends TMappedResult,
|
||||
Right extends TSchema,
|
||||
True extends TSchema,
|
||||
False extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<Left, Right, True, False>
|
||||
>(Left: Left, Right: Right, True: True, False: False, options?: SchemaOptions): TMappedResult<P> {
|
||||
const P = FromMappedResult(Left, Right, True, False, options)
|
||||
return MappedResult(P) as never
|
||||
}
|
||||
55
src/type/extends/extends-undefined.ts
Normal file
55
src/type/extends/extends-undefined.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema } from '../schema/index'
|
||||
import type { TIntersect } from '../intersect/index'
|
||||
import type { TUnion } from '../union/index'
|
||||
import type { TNot } from '../not/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
/** Fast undefined check used for properties of type undefined */
|
||||
function Intersect(schema: TIntersect) {
|
||||
return schema.allOf.every((schema) => ExtendsUndefinedCheck(schema))
|
||||
}
|
||||
function Union(schema: TUnion) {
|
||||
return schema.anyOf.some((schema) => ExtendsUndefinedCheck(schema))
|
||||
}
|
||||
function Not(schema: TNot) {
|
||||
return !ExtendsUndefinedCheck(schema.not)
|
||||
}
|
||||
/** Fast undefined check used for properties of type undefined */
|
||||
// prettier-ignore
|
||||
export function ExtendsUndefinedCheck(schema: TSchema): boolean {
|
||||
return (
|
||||
schema[Kind] === 'Intersect' ? Intersect(schema as TIntersect) :
|
||||
schema[Kind] === 'Union' ? Union(schema as TUnion) :
|
||||
schema[Kind] === 'Not' ? Not(schema as TNot) :
|
||||
schema[Kind] === 'Undefined' ? true :
|
||||
false
|
||||
)
|
||||
}
|
||||
80
src/type/extends/extends.ts
Normal file
80
src/type/extends/extends.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Static } from '../static/index'
|
||||
import { type TUnion, Union } from '../union/index'
|
||||
import { TMappedKey, TMappedResult } from '../mapped/index'
|
||||
import { ExtendsCheck, ExtendsResult } from './extends-check'
|
||||
import { UnionToTuple } from '../helpers/index'
|
||||
import { ExtendsFromMappedKey, type TExtendsFromMappedKey } from './extends-from-mapped-key'
|
||||
import { ExtendsFromMappedResult, type TExtendsFromMappedResult } from './extends-from-mapped-result'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsMappedKey, IsMappedResult } from '../guard/kind'
|
||||
|
||||
// prettier-ignore
|
||||
type TExtendsResolve<L extends TSchema, R extends TSchema, T extends TSchema, U extends TSchema> = (
|
||||
(Static<L> extends Static<R> ? T : U) extends infer O extends TSchema ?
|
||||
UnionToTuple<O> extends [infer X extends TSchema, infer Y extends TSchema]
|
||||
? TUnion<[X, Y]>
|
||||
: O
|
||||
: never
|
||||
)
|
||||
// prettier-ignore
|
||||
function ExtendsResolve<L extends TSchema, R extends TSchema, T extends TSchema, U extends TSchema>(left: L, right: R, trueType: T, falseType: U): TExtendsResolve<L, R, T, U> {
|
||||
const R = ExtendsCheck(left, right)
|
||||
return (
|
||||
R === ExtendsResult.Union ? Union([trueType, falseType]) :
|
||||
R === ExtendsResult.True ? trueType :
|
||||
falseType
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TExtends
|
||||
// ------------------------------------------------------------------
|
||||
export type TExtends<L extends TSchema, R extends TSchema, T extends TSchema, F extends TSchema> = TExtendsResolve<L, R, T, F>
|
||||
|
||||
/** `[Json]` Creates a Conditional type */
|
||||
export function Extends<L extends TMappedResult, R extends TSchema, T extends TSchema, F extends TSchema>(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtendsFromMappedResult<L, R, T, F>
|
||||
/** `[Json]` Creates a Conditional type */
|
||||
export function Extends<L extends TMappedKey, R extends TSchema, T extends TSchema, F extends TSchema>(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtendsFromMappedKey<L, R, T, F>
|
||||
/** `[Json]` Creates a Conditional type */
|
||||
export function Extends<L extends TSchema, R extends TSchema, T extends TSchema, F extends TSchema>(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtends<L, R, T, F>
|
||||
/** `[Json]` Creates a Conditional type */
|
||||
export function Extends<L extends TSchema, R extends TSchema, T extends TSchema, F extends TSchema>(L: L, R: R, T: T, F: F, options?: SchemaOptions) {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsMappedResult(L) ? ExtendsFromMappedResult(L, R, T, F, options) :
|
||||
IsMappedKey(L) ? CreateType(ExtendsFromMappedKey(L, R, T, F, options)) :
|
||||
CreateType(ExtendsResolve(L, R, T, F), options)
|
||||
) as never
|
||||
}
|
||||
33
src/type/extends/index.ts
Normal file
33
src/type/extends/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './extends-check'
|
||||
export * from './extends-from-mapped-key'
|
||||
export * from './extends-from-mapped-result'
|
||||
export * from './extends-undefined'
|
||||
export * from './extends'
|
||||
89
src/type/extract/extract-from-mapped-result.ts
Normal file
89
src/type/extract/extract-from-mapped-result.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import { MappedResult, type TMappedResult } from '../mapped/index'
|
||||
import { Extract, type TExtract } from './extract'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperties<
|
||||
P extends TProperties,
|
||||
T extends TSchema
|
||||
> = (
|
||||
{ [K2 in keyof P]: TExtract<P[K2], T> }
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromProperties<
|
||||
P extends TProperties,
|
||||
T extends TSchema
|
||||
>(P: P, T: T): 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
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema
|
||||
> = (
|
||||
TFromProperties<R['properties'], T>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema
|
||||
>(R: R, T: T): TFromMappedResult<R, T> {
|
||||
return FromProperties(R.properties, T) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ExtractFromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExtractFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<R, T>
|
||||
> = (
|
||||
TMappedResult<P>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function ExtractFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<R, T>
|
||||
>(R: R, T: T): TMappedResult<P> {
|
||||
const P = FromMappedResult(R, T)
|
||||
return MappedResult(P) as never
|
||||
}
|
||||
39
src/type/extract/extract-from-template-literal.ts
Normal file
39
src/type/extract/extract-from-template-literal.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema } from '../schema/index'
|
||||
import { Extract, type TExtract } from './extract'
|
||||
import { TemplateLiteralToUnion, type TTemplateLiteral, type TTemplateLiteralToUnion } from '../template-literal/index'
|
||||
|
||||
// prettier-ignore
|
||||
export type TExtractFromTemplateLiteral<L extends TTemplateLiteral, R extends TSchema> = (
|
||||
TExtract<TTemplateLiteralToUnion<L>, R>
|
||||
)
|
||||
export function ExtractFromTemplateLiteral<L extends TTemplateLiteral, R extends TSchema>(L: L, R: R): TExtractFromTemplateLiteral<L, R> {
|
||||
return Extract(TemplateLiteralToUnion(L), R) as never
|
||||
}
|
||||
83
src/type/extract/extract.ts
Normal file
83
src/type/extract/extract.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { AssertRest, AssertType, UnionToTuple } from '../helpers/index'
|
||||
import type { TMappedResult } from '../mapped/index'
|
||||
import { Union, type TUnion } from '../union/index'
|
||||
import { type Static } from '../static/index'
|
||||
import { Never, type TNever } from '../never/index'
|
||||
import { type TUnionEvaluated } from '../union/index'
|
||||
import { type TTemplateLiteral } from '../template-literal/index'
|
||||
import { ExtendsCheck, ExtendsResult } from '../extends/index'
|
||||
import { ExtractFromMappedResult, type TExtractFromMappedResult } from './extract-from-mapped-result'
|
||||
import { ExtractFromTemplateLiteral, type TExtractFromTemplateLiteral } from './extract-from-template-literal'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsMappedResult, IsTemplateLiteral, IsUnion } from '../guard/kind'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ExtractRest
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TExtractRest<L extends TSchema[], R extends TSchema> = AssertRest<UnionToTuple<
|
||||
{ [K in keyof L]: Static<AssertType<L[K]>> extends Static<R> ? L[K] : never
|
||||
}[number]>> extends infer R extends TSchema[] ? TUnionEvaluated<R> : never
|
||||
|
||||
function ExtractRest<L extends TSchema[], R extends TSchema>(L: [...L], R: R) {
|
||||
const extracted = L.filter((inner) => ExtendsCheck(inner, R) !== ExtendsResult.False)
|
||||
return extracted.length === 1 ? extracted[0] : Union(extracted)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TExtract
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExtract<L extends TSchema, U extends TSchema> = (
|
||||
L extends TUnion<infer S> ? TExtractRest<S, U> :
|
||||
L extends U ? L : TNever
|
||||
)
|
||||
/** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */
|
||||
export function Extract<L extends TMappedResult, R extends TSchema>(type: L, union: R, options?: SchemaOptions): TExtractFromMappedResult<L, R>
|
||||
/** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */
|
||||
export function Extract<L extends TTemplateLiteral, R extends TSchema>(type: L, union: R, options?: SchemaOptions): TExtractFromTemplateLiteral<L, R>
|
||||
/** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */
|
||||
export function Extract<L extends TSchema, R extends TSchema>(type: L, union: R, options?: SchemaOptions): TExtract<L, R>
|
||||
/** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */
|
||||
export function Extract(L: TSchema, R: TSchema, options?: SchemaOptions): never {
|
||||
// overloads
|
||||
if (IsTemplateLiteral(L)) return CreateType(ExtractFromTemplateLiteral(L, R), options) as never
|
||||
if (IsMappedResult(L)) return CreateType(ExtractFromMappedResult(L, R), options) as never
|
||||
// prettier-ignore
|
||||
return CreateType(
|
||||
IsUnion(L) ? ExtractRest(L.anyOf, R) :
|
||||
ExtendsCheck(L, R) !== ExtendsResult.False ? L : Never()
|
||||
, options) as never
|
||||
}
|
||||
31
src/type/extract/index.ts
Normal file
31
src/type/extract/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './extract-from-mapped-result'
|
||||
export * from './extract-from-template-literal'
|
||||
export * from './extract'
|
||||
71
src/type/function/function.ts
Normal file
71
src/type/function/function.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Static } from '../static/index'
|
||||
import type { Ensure } from '../helpers/index'
|
||||
import type { TReadonlyOptional } from '../readonly-optional/index'
|
||||
import type { TReadonly } from '../readonly/index'
|
||||
import type { TOptional } from '../optional/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// StaticFunction
|
||||
// ------------------------------------------------------------------
|
||||
type StaticReturnType<U extends TSchema, P extends unknown[]> = Static<U, P>
|
||||
// prettier-ignore
|
||||
type StaticParameter<T extends TSchema, P extends unknown[]> =
|
||||
T extends TReadonlyOptional<T> ? [Readonly<Static<T, P>>?] :
|
||||
T extends TReadonly<T> ? [Readonly<Static<T, P>>] :
|
||||
T extends TOptional<T> ? [Static<T, P>?] :
|
||||
[Static<T, P>]
|
||||
// prettier-ignore
|
||||
type StaticParameters<T extends TSchema[], P extends unknown[], Acc extends unknown[] = []> = (
|
||||
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
|
||||
? StaticParameters<R, P, [...Acc, ...StaticParameter<L, P>]>
|
||||
: Acc
|
||||
)
|
||||
// prettier-ignore
|
||||
type StaticFunction<T extends TSchema[], U extends TSchema, P extends unknown[]> =
|
||||
Ensure<(...param: StaticParameters<T, P>) => StaticReturnType<U, P>>
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TFunction
|
||||
// ------------------------------------------------------------------
|
||||
export interface TFunction<T extends TSchema[] = TSchema[], U extends TSchema = TSchema> extends TSchema {
|
||||
[Kind]: 'Function'
|
||||
static: StaticFunction<T, U, this['params']>
|
||||
type: 'Function'
|
||||
parameters: T
|
||||
returns: U
|
||||
}
|
||||
/** `[JavaScript]` Creates a Function type */
|
||||
export function Function<T extends TSchema[], U extends TSchema>(parameters: [...T], returns: U, options?: SchemaOptions): TFunction<T, U> {
|
||||
return CreateType({ [Kind]: 'Function', type: 'Function', parameters, returns }, options) as never
|
||||
}
|
||||
29
src/type/function/index.ts
Normal file
29
src/type/function/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './function'
|
||||
31
src/type/guard/index.ts
Normal file
31
src/type/guard/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * as KindGuard from './kind'
|
||||
export * as TypeGuard from './type'
|
||||
export * as ValueGuard from './value'
|
||||
307
src/type/guard/kind.ts
Normal file
307
src/type/guard/kind.ts
Normal file
@@ -0,0 +1,307 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import * as ValueGuard from './value'
|
||||
import { Kind, Hint, TransformKind, ReadonlyKind, OptionalKind } from '../symbols/index'
|
||||
import { TransformOptions } from '../transform/index'
|
||||
|
||||
import type { TAny } from '../any/index'
|
||||
import type { TArgument } from '../argument/index'
|
||||
import type { TArray } from '../array/index'
|
||||
import type { TAsyncIterator } from '../async-iterator/index'
|
||||
import type { TBoolean } from '../boolean/index'
|
||||
import type { TComputed } from '../computed/index'
|
||||
import type { TBigInt } from '../bigint/index'
|
||||
import type { TConstructor } from '../constructor/index'
|
||||
import type { TFunction } from '../function/index'
|
||||
import type { TImport } from '../module/index'
|
||||
import type { TInteger } from '../integer/index'
|
||||
import type { TIntersect } from '../intersect/index'
|
||||
import type { TIterator } from '../iterator/index'
|
||||
import type { TLiteral, TLiteralValue } from '../literal/index'
|
||||
import type { TMappedKey, TMappedResult } from '../mapped/index'
|
||||
import type { TNever } from '../never/index'
|
||||
import type { TNot } from '../not/index'
|
||||
import type { TNull } from '../null/index'
|
||||
import type { TNumber } from '../number/index'
|
||||
import type { TObject, TProperties } from '../object/index'
|
||||
import type { TOptional } from '../optional/index'
|
||||
import type { TPromise } from '../promise/index'
|
||||
import type { TReadonly } from '../readonly/index'
|
||||
import type { TRecord } from '../record/index'
|
||||
import type { TRef } from '../ref/index'
|
||||
import type { TRegExp } from '../regexp/index'
|
||||
import type { TSchema } from '../schema/index'
|
||||
import type { TString } from '../string/index'
|
||||
import type { TSymbol } from '../symbol/index'
|
||||
import type { TTemplateLiteral } from '../template-literal/index'
|
||||
import type { TTuple } from '../tuple/index'
|
||||
import type { TUint8Array } from '../uint8array/index'
|
||||
import type { TUndefined } from '../undefined/index'
|
||||
import type { TUnknown } from '../unknown/index'
|
||||
import type { TUnion } from '../union/index'
|
||||
import type { TUnsafe } from '../unsafe/index'
|
||||
import type { TVoid } from '../void/index'
|
||||
import type { TDate } from '../date/index'
|
||||
import type { TThis } from '../recursive/index'
|
||||
|
||||
/** `[Kind-Only]` Returns true if this value has a Readonly symbol */
|
||||
export function IsReadonly<T extends TSchema>(value: T): value is TReadonly<T> {
|
||||
return ValueGuard.IsObject(value) && value[ReadonlyKind] === 'Readonly'
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if this value has a Optional symbol */
|
||||
export function IsOptional<T extends TSchema>(value: T): value is TOptional<T> {
|
||||
return ValueGuard.IsObject(value) && value[OptionalKind] === 'Optional'
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TAny */
|
||||
export function IsAny(value: unknown): value is TAny {
|
||||
return IsKindOf(value, 'Any')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TArgument */
|
||||
export function IsArgument(value: unknown): value is TArgument {
|
||||
return IsKindOf(value, 'Argument')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TArray */
|
||||
export function IsArray(value: unknown): value is TArray {
|
||||
return IsKindOf(value, 'Array')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TAsyncIterator */
|
||||
export function IsAsyncIterator(value: unknown): value is TAsyncIterator {
|
||||
return IsKindOf(value, 'AsyncIterator')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TBigInt */
|
||||
export function IsBigInt(value: unknown): value is TBigInt {
|
||||
return IsKindOf(value, 'BigInt')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TBoolean */
|
||||
export function IsBoolean(value: unknown): value is TBoolean {
|
||||
return IsKindOf(value, 'Boolean')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TComputed */
|
||||
export function IsComputed(value: unknown): value is TComputed {
|
||||
return IsKindOf(value, 'Computed')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TConstructor */
|
||||
export function IsConstructor(value: unknown): value is TConstructor {
|
||||
return IsKindOf(value, 'Constructor')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TDate */
|
||||
export function IsDate(value: unknown): value is TDate {
|
||||
return IsKindOf(value, 'Date')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TFunction */
|
||||
export function IsFunction(value: unknown): value is TFunction {
|
||||
return IsKindOf(value, 'Function')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TInteger */
|
||||
export function IsImport(value: unknown): value is TImport {
|
||||
return IsKindOf(value, 'Import')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TInteger */
|
||||
export function IsInteger(value: unknown): value is TInteger {
|
||||
return IsKindOf(value, 'Integer')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given schema is TProperties */
|
||||
export function IsProperties(value: unknown): value is TProperties {
|
||||
return ValueGuard.IsObject(value)
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TIntersect */
|
||||
export function IsIntersect(value: unknown): value is TIntersect {
|
||||
return IsKindOf(value, 'Intersect')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TIterator */
|
||||
export function IsIterator(value: unknown): value is TIterator {
|
||||
return IsKindOf(value, 'Iterator')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is a TKind with the given name. */
|
||||
export function IsKindOf<T extends string>(value: unknown, kind: T): value is Record<PropertyKey, unknown> & { [Kind]: T } {
|
||||
return ValueGuard.IsObject(value) && Kind in value && value[Kind] === kind
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TLiteral<string> */
|
||||
export function IsLiteralString(value: unknown): value is TLiteral<string> {
|
||||
return IsLiteral(value) && ValueGuard.IsString(value.const)
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TLiteral<number> */
|
||||
export function IsLiteralNumber(value: unknown): value is TLiteral<number> {
|
||||
return IsLiteral(value) && ValueGuard.IsNumber(value.const)
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TLiteral<boolean> */
|
||||
export function IsLiteralBoolean(value: unknown): value is TLiteral<boolean> {
|
||||
return IsLiteral(value) && ValueGuard.IsBoolean(value.const)
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TLiteralValue */
|
||||
export function IsLiteralValue(value: unknown): value is TLiteralValue {
|
||||
return ValueGuard.IsBoolean(value) || ValueGuard.IsNumber(value) || ValueGuard.IsString(value)
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TLiteral */
|
||||
export function IsLiteral(value: unknown): value is TLiteral {
|
||||
return IsKindOf(value, 'Literal')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is a TMappedKey */
|
||||
export function IsMappedKey(value: unknown): value is TMappedKey {
|
||||
return IsKindOf(value, 'MappedKey')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TMappedResult */
|
||||
export function IsMappedResult(value: unknown): value is TMappedResult {
|
||||
return IsKindOf(value, 'MappedResult')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TNever */
|
||||
export function IsNever(value: unknown): value is TNever {
|
||||
return IsKindOf(value, 'Never')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TNot */
|
||||
export function IsNot(value: unknown): value is TNot {
|
||||
return IsKindOf(value, 'Not')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TNull */
|
||||
export function IsNull(value: unknown): value is TNull {
|
||||
return IsKindOf(value, 'Null')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TNumber */
|
||||
export function IsNumber(value: unknown): value is TNumber {
|
||||
return IsKindOf(value, 'Number')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TObject */
|
||||
export function IsObject(value: unknown): value is TObject {
|
||||
return IsKindOf(value, 'Object')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TPromise */
|
||||
export function IsPromise(value: unknown): value is TPromise {
|
||||
return IsKindOf(value, 'Promise')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TRecord */
|
||||
export function IsRecord(value: unknown): value is TRecord {
|
||||
return IsKindOf(value, 'Record')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if this value is TRecursive */
|
||||
export function IsRecursive(value: unknown): value is { [Hint]: 'Recursive' } {
|
||||
return ValueGuard.IsObject(value) && Hint in value && value[Hint] === 'Recursive'
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TRef */
|
||||
export function IsRef(value: unknown): value is TRef {
|
||||
return IsKindOf(value, 'Ref')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TRegExp */
|
||||
export function IsRegExp(value: unknown): value is TRegExp {
|
||||
return IsKindOf(value, 'RegExp')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TString */
|
||||
export function IsString(value: unknown): value is TString {
|
||||
return IsKindOf(value, 'String')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TSymbol */
|
||||
export function IsSymbol(value: unknown): value is TSymbol {
|
||||
return IsKindOf(value, 'Symbol')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TTemplateLiteral */
|
||||
export function IsTemplateLiteral(value: unknown): value is TTemplateLiteral {
|
||||
return IsKindOf(value, 'TemplateLiteral')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TThis */
|
||||
export function IsThis(value: unknown): value is TThis {
|
||||
return IsKindOf(value, 'This')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true of this value is TTransform */
|
||||
export function IsTransform(value: unknown): value is { [TransformKind]: TransformOptions } {
|
||||
return ValueGuard.IsObject(value) && TransformKind in value
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TTuple */
|
||||
export function IsTuple(value: unknown): value is TTuple {
|
||||
return IsKindOf(value, 'Tuple')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TUndefined */
|
||||
export function IsUndefined(value: unknown): value is TUndefined {
|
||||
return IsKindOf(value, 'Undefined')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TUnion */
|
||||
export function IsUnion(value: unknown): value is TUnion {
|
||||
return IsKindOf(value, 'Union')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TUint8Array */
|
||||
export function IsUint8Array(value: unknown): value is TUint8Array {
|
||||
return IsKindOf(value, 'Uint8Array')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TUnknown */
|
||||
export function IsUnknown(value: unknown): value is TUnknown {
|
||||
return IsKindOf(value, 'Unknown')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is a raw TUnsafe */
|
||||
export function IsUnsafe(value: unknown): value is TUnsafe<unknown> {
|
||||
return IsKindOf(value, 'Unsafe')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TVoid */
|
||||
export function IsVoid(value: unknown): value is TVoid {
|
||||
return IsKindOf(value, 'Void')
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TKind */
|
||||
export function IsKind(value: unknown): value is Record<PropertyKey, unknown> & { [Kind]: string } {
|
||||
return ValueGuard.IsObject(value) && Kind in value && ValueGuard.IsString(value[Kind])
|
||||
}
|
||||
/** `[Kind-Only]` Returns true if the given value is TSchema */
|
||||
export function IsSchema(value: unknown): value is TSchema {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsAny(value) ||
|
||||
IsArgument(value) ||
|
||||
IsArray(value) ||
|
||||
IsBoolean(value) ||
|
||||
IsBigInt(value) ||
|
||||
IsAsyncIterator(value) ||
|
||||
IsComputed(value) ||
|
||||
IsConstructor(value) ||
|
||||
IsDate(value) ||
|
||||
IsFunction(value) ||
|
||||
IsInteger(value) ||
|
||||
IsIntersect(value) ||
|
||||
IsIterator(value) ||
|
||||
IsLiteral(value) ||
|
||||
IsMappedKey(value) ||
|
||||
IsMappedResult(value) ||
|
||||
IsNever(value) ||
|
||||
IsNot(value) ||
|
||||
IsNull(value) ||
|
||||
IsNumber(value) ||
|
||||
IsObject(value) ||
|
||||
IsPromise(value) ||
|
||||
IsRecord(value) ||
|
||||
IsRef(value) ||
|
||||
IsRegExp(value) ||
|
||||
IsString(value) ||
|
||||
IsSymbol(value) ||
|
||||
IsTemplateLiteral(value) ||
|
||||
IsThis(value) ||
|
||||
IsTuple(value) ||
|
||||
IsUndefined(value) ||
|
||||
IsUnion(value) ||
|
||||
IsUint8Array(value) ||
|
||||
IsUnknown(value) ||
|
||||
IsUnsafe(value) ||
|
||||
IsVoid(value) ||
|
||||
IsKind(value)
|
||||
)
|
||||
}
|
||||
659
src/type/guard/type.ts
Normal file
659
src/type/guard/type.ts
Normal file
@@ -0,0 +1,659 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import * as ValueGuard from './value'
|
||||
import { Kind, Hint, TransformKind, ReadonlyKind, OptionalKind } from '../symbols/index'
|
||||
import { TypeBoxError } from '../error/index'
|
||||
import { TransformOptions } from '../transform/index'
|
||||
|
||||
import type { TAny } from '../any/index'
|
||||
import type { TArgument } from '../argument/index'
|
||||
import type { TArray } from '../array/index'
|
||||
import type { TAsyncIterator } from '../async-iterator/index'
|
||||
import type { TBoolean } from '../boolean/index'
|
||||
import type { TComputed } from '../computed/index'
|
||||
import type { TBigInt } from '../bigint/index'
|
||||
import type { TConstructor } from '../constructor/index'
|
||||
import type { TFunction } from '../function/index'
|
||||
import type { TImport } from '../module/index'
|
||||
import type { TInteger } from '../integer/index'
|
||||
import type { TIntersect } from '../intersect/index'
|
||||
import type { TIterator } from '../iterator/index'
|
||||
import type { TLiteral, TLiteralValue } from '../literal/index'
|
||||
import type { TMappedKey, TMappedResult } from '../mapped/index'
|
||||
import type { TNever } from '../never/index'
|
||||
import type { TNot } from '../not/index'
|
||||
import type { TNull } from '../null/index'
|
||||
import type { TNumber } from '../number/index'
|
||||
import type { TObject, TAdditionalProperties, TProperties } from '../object/index'
|
||||
import type { TOptional } from '../optional/index'
|
||||
import type { TPromise } from '../promise/index'
|
||||
import type { TReadonly } from '../readonly/index'
|
||||
import type { TRecord } from '../record/index'
|
||||
import type { TRef } from '../ref/index'
|
||||
import type { TRegExp } from '../regexp/index'
|
||||
import type { TSchema } from '../schema/index'
|
||||
import type { TString } from '../string/index'
|
||||
import type { TSymbol } from '../symbol/index'
|
||||
import type { TTemplateLiteral } from '../template-literal/index'
|
||||
import type { TTuple } from '../tuple/index'
|
||||
import type { TUint8Array } from '../uint8array/index'
|
||||
import type { TUndefined } from '../undefined/index'
|
||||
import type { TUnion } from '../union/index'
|
||||
import type { TUnknown } from '../unknown/index'
|
||||
import type { TUnsafe } from '../unsafe/index'
|
||||
import type { TVoid } from '../void/index'
|
||||
import type { TDate } from '../date/index'
|
||||
import type { TThis } from '../recursive/index'
|
||||
|
||||
export class TypeGuardUnknownTypeError extends TypeBoxError {}
|
||||
|
||||
const KnownTypes = [
|
||||
'Argument',
|
||||
'Any',
|
||||
'Array',
|
||||
'AsyncIterator',
|
||||
'BigInt',
|
||||
'Boolean',
|
||||
'Computed',
|
||||
'Constructor',
|
||||
'Date',
|
||||
'Enum',
|
||||
'Function',
|
||||
'Integer',
|
||||
'Intersect',
|
||||
'Iterator',
|
||||
'Literal',
|
||||
'MappedKey',
|
||||
'MappedResult',
|
||||
'Not',
|
||||
'Null',
|
||||
'Number',
|
||||
'Object',
|
||||
'Promise',
|
||||
'Record',
|
||||
'Ref',
|
||||
'RegExp',
|
||||
'String',
|
||||
'Symbol',
|
||||
'TemplateLiteral',
|
||||
'This',
|
||||
'Tuple',
|
||||
'Undefined',
|
||||
'Union',
|
||||
'Uint8Array',
|
||||
'Unknown',
|
||||
'Void',
|
||||
]
|
||||
function IsPattern(value: unknown): value is string {
|
||||
try {
|
||||
new RegExp(value as string)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
function IsControlCharacterFree(value: unknown): value is string {
|
||||
if (!ValueGuard.IsString(value)) return false
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const code = value.charCodeAt(i)
|
||||
if ((code >= 7 && code <= 13) || code === 27 || code === 127) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
function IsAdditionalProperties(value: unknown): value is TAdditionalProperties {
|
||||
return IsOptionalBoolean(value) || IsSchema(value)
|
||||
}
|
||||
function IsOptionalBigInt(value: unknown): value is bigint | undefined {
|
||||
return ValueGuard.IsUndefined(value) || ValueGuard.IsBigInt(value)
|
||||
}
|
||||
function IsOptionalNumber(value: unknown): value is number | undefined {
|
||||
return ValueGuard.IsUndefined(value) || ValueGuard.IsNumber(value)
|
||||
}
|
||||
function IsOptionalBoolean(value: unknown): value is boolean | undefined {
|
||||
return ValueGuard.IsUndefined(value) || ValueGuard.IsBoolean(value)
|
||||
}
|
||||
function IsOptionalString(value: unknown): value is string | undefined {
|
||||
return ValueGuard.IsUndefined(value) || ValueGuard.IsString(value)
|
||||
}
|
||||
function IsOptionalPattern(value: unknown): value is string | undefined {
|
||||
return ValueGuard.IsUndefined(value) || (ValueGuard.IsString(value) && IsControlCharacterFree(value) && IsPattern(value))
|
||||
}
|
||||
function IsOptionalFormat(value: unknown): value is string | undefined {
|
||||
return ValueGuard.IsUndefined(value) || (ValueGuard.IsString(value) && IsControlCharacterFree(value))
|
||||
}
|
||||
function IsOptionalSchema(value: unknown): value is boolean | undefined {
|
||||
return ValueGuard.IsUndefined(value) || IsSchema(value)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Modifiers
|
||||
// ------------------------------------------------------------------
|
||||
/** Returns true if this value has a Readonly symbol */
|
||||
export function IsReadonly<T extends TSchema>(value: T): value is TReadonly<T> {
|
||||
return ValueGuard.IsObject(value) && value[ReadonlyKind] === 'Readonly'
|
||||
}
|
||||
/** Returns true if this value has a Optional symbol */
|
||||
export function IsOptional<T extends TSchema>(value: T): value is TOptional<T> {
|
||||
return ValueGuard.IsObject(value) && value[OptionalKind] === 'Optional'
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Types
|
||||
// ------------------------------------------------------------------
|
||||
/** Returns true if the given value is TAny */
|
||||
export function IsAny(value: unknown): value is TAny {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Any') &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TArgument */
|
||||
export function IsArgument(value: unknown): value is TArgument {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Argument') &&
|
||||
ValueGuard.IsNumber(value.index)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TArray */
|
||||
export function IsArray(value: unknown): value is TArray {
|
||||
return (
|
||||
IsKindOf(value, 'Array') &&
|
||||
value.type === 'array' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsSchema(value.items) &&
|
||||
IsOptionalNumber(value.minItems) &&
|
||||
IsOptionalNumber(value.maxItems) &&
|
||||
IsOptionalBoolean(value.uniqueItems) &&
|
||||
IsOptionalSchema(value.contains) &&
|
||||
IsOptionalNumber(value.minContains) &&
|
||||
IsOptionalNumber(value.maxContains)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TAsyncIterator */
|
||||
export function IsAsyncIterator(value: unknown): value is TAsyncIterator {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'AsyncIterator') &&
|
||||
value.type === 'AsyncIterator' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsSchema(value.items)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TBigInt */
|
||||
export function IsBigInt(value: unknown): value is TBigInt {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'BigInt') &&
|
||||
value.type === 'bigint' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalBigInt(value.exclusiveMaximum) &&
|
||||
IsOptionalBigInt(value.exclusiveMinimum) &&
|
||||
IsOptionalBigInt(value.maximum) &&
|
||||
IsOptionalBigInt(value.minimum) &&
|
||||
IsOptionalBigInt(value.multipleOf)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TBoolean */
|
||||
export function IsBoolean(value: unknown): value is TBoolean {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Boolean') &&
|
||||
value.type === 'boolean' &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TComputed */
|
||||
export function IsComputed(value: unknown): value is TComputed {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Computed') &&
|
||||
ValueGuard.IsString(value.target) &&
|
||||
ValueGuard.IsArray(value.parameters) &&
|
||||
value.parameters.every((schema) => IsSchema(schema))
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TConstructor */
|
||||
export function IsConstructor(value: unknown): value is TConstructor {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Constructor') &&
|
||||
value.type === 'Constructor' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsArray(value.parameters) &&
|
||||
value.parameters.every(schema => IsSchema(schema)) &&
|
||||
IsSchema(value.returns)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TDate */
|
||||
export function IsDate(value: unknown): value is TDate {
|
||||
return (
|
||||
IsKindOf(value, 'Date') &&
|
||||
value.type === 'Date' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalNumber(value.exclusiveMaximumTimestamp) &&
|
||||
IsOptionalNumber(value.exclusiveMinimumTimestamp) &&
|
||||
IsOptionalNumber(value.maximumTimestamp) &&
|
||||
IsOptionalNumber(value.minimumTimestamp) &&
|
||||
IsOptionalNumber(value.multipleOfTimestamp)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TFunction */
|
||||
export function IsFunction(value: unknown): value is TFunction {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Function') &&
|
||||
value.type === 'Function' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsArray(value.parameters) &&
|
||||
value.parameters.every(schema => IsSchema(schema)) &&
|
||||
IsSchema(value.returns)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TImport */
|
||||
export function IsImport(value: unknown): value is TImport {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Import') &&
|
||||
ValueGuard.HasPropertyKey(value, '$defs') &&
|
||||
ValueGuard.IsObject(value.$defs) &&
|
||||
IsProperties(value.$defs) &&
|
||||
ValueGuard.HasPropertyKey(value, '$ref') &&
|
||||
ValueGuard.IsString(value.$ref) &&
|
||||
value.$ref in value.$defs // required
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TInteger */
|
||||
export function IsInteger(value: unknown): value is TInteger {
|
||||
return (
|
||||
IsKindOf(value, 'Integer') &&
|
||||
value.type === 'integer' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalNumber(value.exclusiveMaximum) &&
|
||||
IsOptionalNumber(value.exclusiveMinimum) &&
|
||||
IsOptionalNumber(value.maximum) &&
|
||||
IsOptionalNumber(value.minimum) &&
|
||||
IsOptionalNumber(value.multipleOf)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given schema is TProperties */
|
||||
export function IsProperties(value: unknown): value is TProperties {
|
||||
// prettier-ignore
|
||||
return (
|
||||
ValueGuard.IsObject(value) &&
|
||||
Object.entries(value).every(([key, schema]) => IsControlCharacterFree(key) && IsSchema(schema))
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TIntersect */
|
||||
export function IsIntersect(value: unknown): value is TIntersect {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Intersect') &&
|
||||
(ValueGuard.IsString(value.type) && value.type !== 'object' ? false : true) &&
|
||||
ValueGuard.IsArray(value.allOf) &&
|
||||
value.allOf.every(schema => IsSchema(schema) && !IsTransform(schema)) &&
|
||||
IsOptionalString(value.type) &&
|
||||
(IsOptionalBoolean(value.unevaluatedProperties) || IsOptionalSchema(value.unevaluatedProperties)) &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TIterator */
|
||||
export function IsIterator(value: unknown): value is TIterator {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Iterator') &&
|
||||
value.type === 'Iterator' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsSchema(value.items)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is a TKind with the given name. */
|
||||
export function IsKindOf<T extends string>(value: unknown, kind: T): value is Record<PropertyKey, unknown> & { [Kind]: T } {
|
||||
return ValueGuard.IsObject(value) && Kind in value && value[Kind] === kind
|
||||
}
|
||||
/** Returns true if the given value is TLiteral<string> */
|
||||
export function IsLiteralString(value: unknown): value is TLiteral<string> {
|
||||
return IsLiteral(value) && ValueGuard.IsString(value.const)
|
||||
}
|
||||
/** Returns true if the given value is TLiteral<number> */
|
||||
export function IsLiteralNumber(value: unknown): value is TLiteral<number> {
|
||||
return IsLiteral(value) && ValueGuard.IsNumber(value.const)
|
||||
}
|
||||
/** Returns true if the given value is TLiteral<boolean> */
|
||||
export function IsLiteralBoolean(value: unknown): value is TLiteral<boolean> {
|
||||
return IsLiteral(value) && ValueGuard.IsBoolean(value.const)
|
||||
}
|
||||
/** Returns true if the given value is TLiteral */
|
||||
export function IsLiteral(value: unknown): value is TLiteral {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Literal') &&
|
||||
IsOptionalString(value.$id) && IsLiteralValue(value.const)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is a TLiteralValue */
|
||||
export function IsLiteralValue(value: unknown): value is TLiteralValue {
|
||||
return ValueGuard.IsBoolean(value) || ValueGuard.IsNumber(value) || ValueGuard.IsString(value)
|
||||
}
|
||||
/** Returns true if the given value is a TMappedKey */
|
||||
export function IsMappedKey(value: unknown): value is TMappedKey {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'MappedKey') &&
|
||||
ValueGuard.IsArray(value.keys) &&
|
||||
value.keys.every(key => ValueGuard.IsNumber(key) || ValueGuard.IsString(key))
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TMappedResult */
|
||||
export function IsMappedResult(value: unknown): value is TMappedResult {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'MappedResult') &&
|
||||
IsProperties(value.properties)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TNever */
|
||||
export function IsNever(value: unknown): value is TNever {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Never') &&
|
||||
ValueGuard.IsObject(value.not) &&
|
||||
Object.getOwnPropertyNames(value.not).length === 0
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TNot */
|
||||
export function IsNot(value: unknown): value is TNot {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Not') &&
|
||||
IsSchema(value.not)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TNull */
|
||||
export function IsNull(value: unknown): value is TNull {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Null') &&
|
||||
value.type === 'null' &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TNumber */
|
||||
export function IsNumber(value: unknown): value is TNumber {
|
||||
return (
|
||||
IsKindOf(value, 'Number') &&
|
||||
value.type === 'number' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalNumber(value.exclusiveMaximum) &&
|
||||
IsOptionalNumber(value.exclusiveMinimum) &&
|
||||
IsOptionalNumber(value.maximum) &&
|
||||
IsOptionalNumber(value.minimum) &&
|
||||
IsOptionalNumber(value.multipleOf)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TObject */
|
||||
export function IsObject(value: unknown): value is TObject {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Object') &&
|
||||
value.type === 'object' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsProperties(value.properties) &&
|
||||
IsAdditionalProperties(value.additionalProperties) &&
|
||||
IsOptionalNumber(value.minProperties) &&
|
||||
IsOptionalNumber(value.maxProperties)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TPromise */
|
||||
export function IsPromise(value: unknown): value is TPromise {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Promise') &&
|
||||
value.type === 'Promise' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsSchema(value.item)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TRecord */
|
||||
export function IsRecord(value: unknown): value is TRecord {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Record') &&
|
||||
value.type === 'object' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsAdditionalProperties(value.additionalProperties) &&
|
||||
ValueGuard.IsObject(value.patternProperties) &&
|
||||
((schema: Record<PropertyKey, unknown>) => {
|
||||
const keys = Object.getOwnPropertyNames(schema.patternProperties)
|
||||
return (
|
||||
keys.length === 1 &&
|
||||
IsPattern(keys[0]) &&
|
||||
ValueGuard.IsObject(schema.patternProperties) &&
|
||||
IsSchema(schema.patternProperties[keys[0]])
|
||||
)
|
||||
})(value)
|
||||
)
|
||||
}
|
||||
/** Returns true if this value is TRecursive */
|
||||
export function IsRecursive(value: unknown): value is { [Hint]: 'Recursive' } {
|
||||
return ValueGuard.IsObject(value) && Hint in value && value[Hint] === 'Recursive'
|
||||
}
|
||||
/** Returns true if the given value is TRef */
|
||||
export function IsRef(value: unknown): value is TRef {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Ref') &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsString(value.$ref)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TRegExp */
|
||||
export function IsRegExp(value: unknown): value is TRegExp {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'RegExp') &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsString(value.source) &&
|
||||
ValueGuard.IsString(value.flags) &&
|
||||
IsOptionalNumber(value.maxLength) &&
|
||||
IsOptionalNumber(value.minLength)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TString */
|
||||
export function IsString(value: unknown): value is TString {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'String') &&
|
||||
value.type === 'string' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalNumber(value.minLength) &&
|
||||
IsOptionalNumber(value.maxLength) &&
|
||||
IsOptionalPattern(value.pattern) &&
|
||||
IsOptionalFormat(value.format)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TSymbol */
|
||||
export function IsSymbol(value: unknown): value is TSymbol {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Symbol') &&
|
||||
value.type === 'symbol' &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TTemplateLiteral */
|
||||
export function IsTemplateLiteral(value: unknown): value is TTemplateLiteral {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'TemplateLiteral') &&
|
||||
value.type === 'string' &&
|
||||
ValueGuard.IsString(value.pattern) &&
|
||||
value.pattern[0] === '^' &&
|
||||
value.pattern[value.pattern.length - 1] === '$'
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TThis */
|
||||
export function IsThis(value: unknown): value is TThis {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'This') &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsString(value.$ref)
|
||||
)
|
||||
}
|
||||
/** Returns true of this value is TTransform */
|
||||
export function IsTransform(value: unknown): value is { [TransformKind]: TransformOptions } {
|
||||
return ValueGuard.IsObject(value) && TransformKind in value
|
||||
}
|
||||
/** Returns true if the given value is TTuple */
|
||||
export function IsTuple(value: unknown): value is TTuple {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Tuple') &&
|
||||
value.type === 'array' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsNumber(value.minItems) &&
|
||||
ValueGuard.IsNumber(value.maxItems) &&
|
||||
value.minItems === value.maxItems &&
|
||||
(( // empty
|
||||
ValueGuard.IsUndefined(value.items) &&
|
||||
ValueGuard.IsUndefined(value.additionalItems) &&
|
||||
value.minItems === 0
|
||||
) || (
|
||||
ValueGuard.IsArray(value.items) &&
|
||||
value.items.every(schema => IsSchema(schema))
|
||||
))
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TUndefined */
|
||||
export function IsUndefined(value: unknown): value is TUndefined {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Undefined') &&
|
||||
value.type === 'undefined' &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TUnion<Literal<string | number>[]> */
|
||||
export function IsUnionLiteral(value: unknown): value is TUnion<TLiteral[]> {
|
||||
return IsUnion(value) && value.anyOf.every((schema) => IsLiteralString(schema) || IsLiteralNumber(schema))
|
||||
}
|
||||
/** Returns true if the given value is TUnion */
|
||||
export function IsUnion(value: unknown): value is TUnion {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Union') &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsObject(value) &&
|
||||
ValueGuard.IsArray(value.anyOf) &&
|
||||
value.anyOf.every(schema => IsSchema(schema))
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TUint8Array */
|
||||
export function IsUint8Array(value: unknown): value is TUint8Array {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Uint8Array') &&
|
||||
value.type === 'Uint8Array' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalNumber(value.minByteLength) &&
|
||||
IsOptionalNumber(value.maxByteLength)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TUnknown */
|
||||
export function IsUnknown(value: unknown): value is TUnknown {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Unknown') &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is a raw TUnsafe */
|
||||
export function IsUnsafe(value: unknown): value is TUnsafe<unknown> {
|
||||
return IsKindOf(value, 'Unsafe')
|
||||
}
|
||||
/** Returns true if the given value is TVoid */
|
||||
export function IsVoid(value: unknown): value is TVoid {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Void') &&
|
||||
value.type === 'void' &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TKind */
|
||||
export function IsKind(value: unknown): value is Record<PropertyKey, unknown> & { [Kind]: string } {
|
||||
return ValueGuard.IsObject(value) && Kind in value && ValueGuard.IsString(value[Kind]) && !KnownTypes.includes(value[Kind] as string)
|
||||
}
|
||||
/** Returns true if the given value is TSchema */
|
||||
export function IsSchema(value: unknown): value is TSchema {
|
||||
// prettier-ignore
|
||||
return (
|
||||
ValueGuard.IsObject(value)
|
||||
) && (
|
||||
IsAny(value) ||
|
||||
IsArgument(value) ||
|
||||
IsArray(value) ||
|
||||
IsBoolean(value) ||
|
||||
IsBigInt(value) ||
|
||||
IsAsyncIterator(value) ||
|
||||
IsComputed(value) ||
|
||||
IsConstructor(value) ||
|
||||
IsDate(value) ||
|
||||
IsFunction(value) ||
|
||||
IsInteger(value) ||
|
||||
IsIntersect(value) ||
|
||||
IsIterator(value) ||
|
||||
IsLiteral(value) ||
|
||||
IsMappedKey(value) ||
|
||||
IsMappedResult(value) ||
|
||||
IsNever(value) ||
|
||||
IsNot(value) ||
|
||||
IsNull(value) ||
|
||||
IsNumber(value) ||
|
||||
IsObject(value) ||
|
||||
IsPromise(value) ||
|
||||
IsRecord(value) ||
|
||||
IsRef(value) ||
|
||||
IsRegExp(value) ||
|
||||
IsString(value) ||
|
||||
IsSymbol(value) ||
|
||||
IsTemplateLiteral(value) ||
|
||||
IsThis(value) ||
|
||||
IsTuple(value) ||
|
||||
IsUndefined(value) ||
|
||||
IsUnion(value) ||
|
||||
IsUint8Array(value) ||
|
||||
IsUnknown(value) ||
|
||||
IsUnsafe(value) ||
|
||||
IsVoid(value) ||
|
||||
IsKind(value)
|
||||
)
|
||||
}
|
||||
98
src/type/guard/value.ts
Normal file
98
src/type/guard/value.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// PropertyKey
|
||||
// --------------------------------------------------------------------------
|
||||
/** Returns true if this value has this property key */
|
||||
export function HasPropertyKey<K extends PropertyKey>(value: Record<any, unknown>, key: K): value is Record<PropertyKey, unknown> & { [_ in K]: unknown } {
|
||||
return key in value
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// Object Instances
|
||||
// --------------------------------------------------------------------------
|
||||
/** Returns true if this value is an async iterator */
|
||||
export function IsAsyncIterator(value: unknown): value is AsyncIterableIterator<unknown> {
|
||||
return IsObject(value) && !IsArray(value) && !IsUint8Array(value) && Symbol.asyncIterator in value
|
||||
}
|
||||
/** Returns true if this value is an array */
|
||||
export function IsArray(value: unknown): value is unknown[] {
|
||||
return Array.isArray(value)
|
||||
}
|
||||
/** Returns true if this value is bigint */
|
||||
export function IsBigInt(value: unknown): value is bigint {
|
||||
return typeof value === 'bigint'
|
||||
}
|
||||
/** Returns true if this value is a boolean */
|
||||
export function IsBoolean(value: unknown): value is boolean {
|
||||
return typeof value === 'boolean'
|
||||
}
|
||||
/** Returns true if this value is a Date object */
|
||||
export function IsDate(value: unknown): value is Date {
|
||||
return value instanceof globalThis.Date
|
||||
}
|
||||
/** Returns true if this value is a function */
|
||||
export function IsFunction(value: unknown): value is Function {
|
||||
return typeof value === 'function'
|
||||
}
|
||||
/** Returns true if this value is an iterator */
|
||||
export function IsIterator(value: unknown): value is IterableIterator<unknown> {
|
||||
return IsObject(value) && !IsArray(value) && !IsUint8Array(value) && Symbol.iterator in value
|
||||
}
|
||||
/** Returns true if this value is null */
|
||||
export function IsNull(value: unknown): value is null {
|
||||
return value === null
|
||||
}
|
||||
/** Returns true if this value is number */
|
||||
export function IsNumber(value: unknown): value is number {
|
||||
return typeof value === 'number'
|
||||
}
|
||||
/** Returns true if this value is an object */
|
||||
export function IsObject(value: unknown): value is Record<PropertyKey, unknown> {
|
||||
return typeof value === 'object' && value !== null
|
||||
}
|
||||
/** Returns true if this value is RegExp */
|
||||
export function IsRegExp(value: unknown): value is RegExp {
|
||||
return value instanceof globalThis.RegExp
|
||||
}
|
||||
/** Returns true if this value is string */
|
||||
export function IsString(value: unknown): value is string {
|
||||
return typeof value === 'string'
|
||||
}
|
||||
/** Returns true if this value is symbol */
|
||||
export function IsSymbol(value: unknown): value is symbol {
|
||||
return typeof value === 'symbol'
|
||||
}
|
||||
/** Returns true if this value is a Uint8Array */
|
||||
export function IsUint8Array(value: unknown): value is Uint8Array {
|
||||
return value instanceof globalThis.Uint8Array
|
||||
}
|
||||
/** Returns true if this value is undefined */
|
||||
export function IsUndefined(value: unknown): value is undefined {
|
||||
return value === undefined
|
||||
}
|
||||
69
src/type/helpers/helpers.ts
Normal file
69
src/type/helpers/helpers.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import type { TNever } from '../never/index'
|
||||
// ------------------------------------------------------------------
|
||||
// Helper: Common
|
||||
// ------------------------------------------------------------------
|
||||
export type TupleToIntersect<T extends any[]> = T extends [infer I] ? I : T extends [infer I, ...infer R] ? I & TupleToIntersect<R> : never
|
||||
export type TupleToUnion<T extends any[]> = { [K in keyof T]: T[K] }[number]
|
||||
export type UnionToIntersect<U> = (U extends unknown ? (arg: U) => 0 : never) extends (arg: infer I) => 0 ? I : never
|
||||
export type UnionLast<U> = UnionToIntersect<U extends unknown ? (x: U) => 0 : never> extends (x: infer L) => 0 ? L : never
|
||||
export type UnionToTuple<U, Acc extends unknown[] = [], R = UnionLast<U>> = [U] extends [never] ? Acc : UnionToTuple<Exclude<U, R>, [Extract<U, R>, ...Acc]>
|
||||
export type Trim<T> = T extends `${' '}${infer U}` ? Trim<U> : T extends `${infer U}${' '}` ? Trim<U> : T
|
||||
export type Assert<T, E> = T extends E ? T : never
|
||||
export type Evaluate<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
|
||||
export type Ensure<T> = T extends infer U ? U : never
|
||||
export type EmptyString = ''
|
||||
export type ZeroString = '0'
|
||||
// ------------------------------------------------------------------
|
||||
// Helper: Increment
|
||||
// ------------------------------------------------------------------
|
||||
type IncrementBase = { m: '9'; t: '01'; '0': '1'; '1': '2'; '2': '3'; '3': '4'; '4': '5'; '5': '6'; '6': '7'; '7': '8'; '8': '9'; '9': '0' }
|
||||
type IncrementTake<T extends keyof IncrementBase> = IncrementBase[T]
|
||||
type IncrementStep<T extends string> = T extends IncrementBase['m']
|
||||
? IncrementBase['t']
|
||||
: T extends `${infer L extends keyof IncrementBase}${infer R}`
|
||||
? L extends IncrementBase['m']
|
||||
? `${IncrementTake<L>}${IncrementStep<R>}`
|
||||
: `${IncrementTake<L>}${R}`
|
||||
: never
|
||||
type IncrementReverse<T extends string> = T extends `${infer L}${infer R}` ? `${IncrementReverse<R>}${L}` : T
|
||||
export type TIncrement<T extends string> = IncrementReverse<IncrementStep<IncrementReverse<T>>>
|
||||
/** Increments the given string value + 1 */
|
||||
export function Increment<T extends string>(T: T): TIncrement<T> {
|
||||
return (parseInt(T) + 1).toString() as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Helper: Type Asserts
|
||||
// ------------------------------------------------------------------
|
||||
export type AssertProperties<T> = T extends TProperties ? T : TProperties
|
||||
export type AssertRest<T, E extends TSchema[] = TSchema[]> = T extends E ? T : []
|
||||
export type AssertType<T, E extends TSchema = TSchema> = T extends E ? T : TNever
|
||||
29
src/type/helpers/index.ts
Normal file
29
src/type/helpers/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './helpers'
|
||||
99
src/type/index.ts
Normal file
99
src/type/index.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './any/index'
|
||||
export * from './argument/index'
|
||||
export * from './array/index'
|
||||
export * from './async-iterator/index'
|
||||
export * from './awaited/index'
|
||||
export * from './bigint/index'
|
||||
export * from './boolean/index'
|
||||
export * from './clone/index'
|
||||
export * from './composite/index'
|
||||
export * from './const/index'
|
||||
export * from './constructor/index'
|
||||
export * from './constructor-parameters/index'
|
||||
export * from './date/index'
|
||||
export * from './discard/index'
|
||||
export * from './enum/index'
|
||||
export * from './error/index'
|
||||
export * from './exclude/index'
|
||||
export * from './extends/index'
|
||||
export * from './extract/index'
|
||||
export * from './function/index'
|
||||
export * from './guard/index'
|
||||
export * from './helpers/index'
|
||||
export * from './indexed/index'
|
||||
export * from './instance-type/index'
|
||||
export * from './instantiate/index'
|
||||
export * from './integer/index'
|
||||
export * from './intersect/index'
|
||||
export * from './intrinsic/index'
|
||||
export * from './iterator/index'
|
||||
export * from './keyof/index'
|
||||
export * from './literal/index'
|
||||
export * from './mapped/index'
|
||||
export * from './module/index'
|
||||
export * from './never/index'
|
||||
export * from './not/index'
|
||||
export * from './null/index'
|
||||
export * from './number/index'
|
||||
export * from './object/index'
|
||||
export * from './omit/index'
|
||||
export * from './optional/index'
|
||||
export * from './parameters/index'
|
||||
export * from './partial/index'
|
||||
export * from './patterns/index'
|
||||
export * from './pick/index'
|
||||
export * from './promise/index'
|
||||
export * from './readonly/index'
|
||||
export * from './readonly-optional/index'
|
||||
export * from './record/index'
|
||||
export * from './recursive/index'
|
||||
export * from './ref/index'
|
||||
export * from './regexp/index'
|
||||
export * from './registry/index'
|
||||
export * from './required/index'
|
||||
export * from './rest/index'
|
||||
export * from './return-type/index'
|
||||
export * from './schema/index'
|
||||
export * from './sets/index'
|
||||
export * from './static/index'
|
||||
export * from './string/index'
|
||||
export * from './symbol/index'
|
||||
export * from './symbols/index'
|
||||
export * from './template-literal/index'
|
||||
export * from './transform/index'
|
||||
export * from './tuple/index'
|
||||
export * from './type/index'
|
||||
export * from './uint8array/index'
|
||||
export * from './undefined/index'
|
||||
export * from './union/index'
|
||||
export * from './unknown/index'
|
||||
export * from './unsafe/index'
|
||||
export * from './void/index'
|
||||
32
src/type/indexed/index.ts
Normal file
32
src/type/indexed/index.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './indexed-from-mapped-key'
|
||||
export * from './indexed-from-mapped-result'
|
||||
export * from './indexed-property-keys'
|
||||
export * from './indexed'
|
||||
92
src/type/indexed/indexed-from-mapped-key.ts
Normal file
92
src/type/indexed/indexed-from-mapped-key.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Ensure, Evaluate } from '../helpers/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import { Index, type TIndex } from './indexed'
|
||||
import { MappedResult, type TMappedResult, type TMappedKey } from '../mapped/index'
|
||||
import { Clone } from '../clone/value'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// MappedIndexPropertyKey
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TMappedIndexPropertyKey<Type extends TSchema, Key extends PropertyKey> = {
|
||||
[_ in Key]: TIndex<Type, [Key]>
|
||||
}
|
||||
// prettier-ignore
|
||||
function MappedIndexPropertyKey<Type extends TSchema, Key extends PropertyKey>(type: Type, key: Key, options?: SchemaOptions): TMappedIndexPropertyKey<Type, Key> {
|
||||
return { [key]: Index(type, [key], Clone(options)) } as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// MappedIndexPropertyKeys
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TMappedIndexPropertyKeys<Type extends TSchema, PropertyKeys extends PropertyKey[], Result extends TProperties = {}> = (
|
||||
PropertyKeys extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]]
|
||||
? TMappedIndexPropertyKeys<Type, Right, Result & TMappedIndexPropertyKey<Type, Left>>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
function MappedIndexPropertyKeys<
|
||||
Type extends TSchema,
|
||||
PropertyKeys extends PropertyKey[]
|
||||
>(type: Type, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TMappedIndexPropertyKeys<Type, PropertyKeys> {
|
||||
return propertyKeys.reduce((result, left) => {
|
||||
return { ...result, ...MappedIndexPropertyKey(type, left, options) }
|
||||
}, {} as TProperties) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// MappedIndexProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TMappedIndexProperties<Type extends TSchema, MappedKey extends TMappedKey> = Evaluate<
|
||||
TMappedIndexPropertyKeys<Type, MappedKey['keys']>
|
||||
>
|
||||
// prettier-ignore
|
||||
function MappedIndexProperties<Type extends TSchema, MappedKey extends TMappedKey
|
||||
>(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TMappedIndexProperties<Type, MappedKey> {
|
||||
return MappedIndexPropertyKeys(type, mappedKey.keys, options) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TIndexFromMappedKey
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TIndexFromMappedKey<Type extends TSchema, MappedKey extends TMappedKey,
|
||||
Properties extends TProperties = TMappedIndexProperties<Type, MappedKey>
|
||||
> = (
|
||||
Ensure<TMappedResult<Properties>>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function IndexFromMappedKey<Type extends TSchema, MappedKey extends TMappedKey,
|
||||
Properties extends TProperties = TMappedIndexProperties<Type, MappedKey>
|
||||
>(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TMappedResult<Properties> {
|
||||
const properties = MappedIndexProperties(type, mappedKey, options)
|
||||
return MappedResult(properties) as never
|
||||
}
|
||||
76
src/type/indexed/indexed-from-mapped-result.ts
Normal file
76
src/type/indexed/indexed-from-mapped-result.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import { MappedResult, type TMappedResult } from '../mapped/index'
|
||||
import { IndexPropertyKeys, type TIndexPropertyKeys } from './indexed-property-keys'
|
||||
import { Index, type TIndex } from './index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperties<Type extends TSchema, Properties extends TProperties> = (
|
||||
{ [K2 in keyof Properties]: TIndex<Type, TIndexPropertyKeys<Properties[K2]>> }
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromProperties<Type extends TSchema, Properties extends TProperties>(type: Type, properties: Properties, options?: SchemaOptions): TFromProperties<Type, Properties> {
|
||||
const result = {} as Record<PropertyKey, TSchema>
|
||||
for(const K2 of Object.getOwnPropertyNames(properties)) {
|
||||
result[K2] = Index(type, IndexPropertyKeys(properties[K2]), options)
|
||||
}
|
||||
return result as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromMappedResult<Type extends TSchema, MappedResult extends TMappedResult> = (
|
||||
TFromProperties<Type, MappedResult['properties']>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromMappedResult<Type extends TSchema, MappedResult extends TMappedResult>(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TFromMappedResult<Type, MappedResult> {
|
||||
return FromProperties(type, mappedResult.properties, options) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TIndexFromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TIndexFromMappedResult<Type extends TSchema, MappedResult extends TMappedResult,
|
||||
Properties extends TProperties = TFromMappedResult<Type, MappedResult>
|
||||
> = (
|
||||
TMappedResult<Properties>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function IndexFromMappedResult<Type extends TSchema, MappedResult extends TMappedResult,
|
||||
Properties extends TProperties = TFromMappedResult<Type, MappedResult>
|
||||
>(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TMappedResult<Properties> {
|
||||
const properties = FromMappedResult(type, mappedResult, options)
|
||||
return MappedResult(properties) as never
|
||||
}
|
||||
103
src/type/indexed/indexed-property-keys.ts
Normal file
103
src/type/indexed/indexed-property-keys.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { TemplateLiteralGenerate, type TTemplateLiteralGenerate, type TTemplateLiteral } from '../template-literal/index'
|
||||
import type { TLiteral, TLiteralValue } from '../literal/index'
|
||||
import type { TInteger } from '../integer/index'
|
||||
import type { TNumber } from '../number/index'
|
||||
import type { TSchema } from '../schema/index'
|
||||
import type { TUnion } from '../union/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsTemplateLiteral, IsUnion, IsLiteral, IsNumber, IsInteger } from '../guard/kind'
|
||||
// ------------------------------------------------------------------
|
||||
// FromTemplateLiteral
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromTemplateLiteral<TemplateLiteral extends TTemplateLiteral, Keys extends string[] = TTemplateLiteralGenerate<TemplateLiteral>> = (Keys)
|
||||
// prettier-ignore
|
||||
function FromTemplateLiteral<TemplateLiteral extends TTemplateLiteral>(templateLiteral: TemplateLiteral): TFromTemplateLiteral<TemplateLiteral> {
|
||||
const keys = TemplateLiteralGenerate(templateLiteral) as string[]
|
||||
return keys.map(key => key.toString()) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromUnion
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromUnion<Types extends TSchema[], Result extends string[] = []> = (
|
||||
Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]]
|
||||
? TFromUnion<Right, [...Result, ...TIndexPropertyKeys<Left>]>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromUnion<Types extends TSchema[]>(types: Types): TFromUnion<Types> {
|
||||
const result = [] as string[]
|
||||
for(const type of types) result.push(...IndexPropertyKeys(type))
|
||||
return result as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromLiteral
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromLiteral<LiteralValue extends TLiteralValue> = (
|
||||
LiteralValue extends PropertyKey
|
||||
? [`${LiteralValue}`]
|
||||
: []
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromLiteral<LiteralValue extends TLiteralValue>(literalValue: LiteralValue): TFromLiteral<LiteralValue> {
|
||||
return (
|
||||
[(literalValue as string).toString()] // TS 5.4 observes TLiteralValue as not having a toString()
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// IndexPropertyKeys
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TIndexPropertyKeys<Type extends TSchema> = (
|
||||
Type extends TTemplateLiteral ? TFromTemplateLiteral<Type> :
|
||||
Type extends TUnion<infer Types extends TSchema[]> ? TFromUnion<Types> :
|
||||
Type extends TLiteral<infer Value extends TLiteralValue> ? TFromLiteral<Value> :
|
||||
Type extends TNumber ? ['[number]'] :
|
||||
Type extends TInteger ? ['[number]'] :
|
||||
[]
|
||||
)
|
||||
/** Returns a tuple of PropertyKeys derived from the given TSchema */
|
||||
// prettier-ignore
|
||||
export function IndexPropertyKeys<Type extends TSchema>(type: Type): TIndexPropertyKeys<Type> {
|
||||
return [...new Set<string>((
|
||||
IsTemplateLiteral(type) ? FromTemplateLiteral(type) :
|
||||
IsUnion(type) ? FromUnion(type.anyOf) :
|
||||
IsLiteral(type) ? FromLiteral(type.const) :
|
||||
IsNumber(type) ? ['[number]'] :
|
||||
IsInteger(type) ? ['[number]'] :
|
||||
[]
|
||||
))] as never
|
||||
}
|
||||
300
src/type/indexed/indexed.ts
Normal file
300
src/type/indexed/indexed.ts
Normal file
@@ -0,0 +1,300 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import { TypeBoxError } from '../error/index'
|
||||
|
||||
import { type TSchema, SchemaOptions } from '../schema/index'
|
||||
import { type Assert } from '../helpers/index'
|
||||
import { type TComputed, Computed } from '../computed/index'
|
||||
import { type TNever, Never } from '../never/index'
|
||||
import { type TArray } from '../array/index'
|
||||
import { type TIntersect } from '../intersect/index'
|
||||
import { type TMappedResult, type TMappedKey } from '../mapped/index'
|
||||
import { type TObject, type TProperties } from '../object/index'
|
||||
import { type TUnion } from '../union/index'
|
||||
import { type TRecursive } from '../recursive/index'
|
||||
import { type TRef } from '../ref/index'
|
||||
import { type TTuple } from '../tuple/index'
|
||||
|
||||
import { IntersectEvaluated, type TIntersectEvaluated } from '../intersect/index'
|
||||
import { UnionEvaluated, type TUnionEvaluated } from '../union/index'
|
||||
|
||||
import { IndexPropertyKeys, type TIndexPropertyKeys } from './indexed-property-keys'
|
||||
import { IndexFromMappedKey, type TIndexFromMappedKey } from './indexed-from-mapped-key'
|
||||
import { IndexFromMappedResult, type TIndexFromMappedResult } from './indexed-from-mapped-result'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsArray, IsIntersect, IsObject, IsMappedKey, IsMappedResult, IsNever, IsSchema, IsTuple, IsUnion, IsRef } from '../guard/kind'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FromRest
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromRest<Types extends TSchema[], Key extends PropertyKey, Result extends TSchema[] = []> = (
|
||||
Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]]
|
||||
? TFromRest<Right, Key, [...Result, Assert<TIndexFromPropertyKey<Left, Key>, TSchema>]>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromRest<Types extends TSchema[], Key extends PropertyKey>(types: [...Types], key: Key): TFromRest<Types, Key> {
|
||||
return types.map(type => IndexFromPropertyKey(type, key)) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromIntersectRest
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromIntersectRest<Types extends TSchema[], Result extends TSchema[] = []> = (
|
||||
Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]]
|
||||
? Left extends TNever
|
||||
? TFromIntersectRest<Right, [...Result]>
|
||||
: TFromIntersectRest<Right, [...Result, Left]>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromIntersectRest<Types extends TSchema[]>(types: [...Types]): TFromIntersectRest<Types> {
|
||||
return types.filter(type => !IsNever(type)) as never
|
||||
}
|
||||
// prettier-ignore
|
||||
type TFromIntersect<Types extends TSchema[], Key extends PropertyKey> = (
|
||||
TIntersectEvaluated<TFromIntersectRest<TFromRest<Types, Key>>>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromIntersect<Types extends TSchema[], Key extends PropertyKey>(types: [...Types], key: Key): TFromIntersect<Types, Key> {
|
||||
return (
|
||||
IntersectEvaluated(FromIntersectRest(FromRest(types as TSchema[], key)))
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromUnionRest
|
||||
//
|
||||
// The following accept a tuple of indexed key results. When evaluating
|
||||
// these results, we check if any result evaluated to TNever. For key
|
||||
// indexed unions, a TNever result indicates that the key was not
|
||||
// present on the variant. In these cases, we must evaluate the indexed
|
||||
// union to TNever (as given by a [] result). This logic aligns to the
|
||||
// following behaviour.
|
||||
//
|
||||
// Non-Overlapping Union
|
||||
//
|
||||
// type A = { a: string }
|
||||
// type B = { b: string }
|
||||
// type C = (A | B) & { a: number } // C is { a: number }
|
||||
//
|
||||
// Overlapping Union
|
||||
//
|
||||
// type A = { a: string }
|
||||
// type B = { a: string }
|
||||
// type C = (A | B) & { a: number } // C is { a: never }
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromUnionRest<Types extends TSchema[], Result extends TSchema[] = []> =
|
||||
Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]]
|
||||
? Left extends TNever
|
||||
? []
|
||||
: TFromUnionRest<Right, [Left, ...Result]>
|
||||
: Result
|
||||
// prettier-ignore
|
||||
function FromUnionRest<Types extends TSchema[]>(types: [...Types]): TFromUnionRest<Types> {
|
||||
return (
|
||||
types.some(L => IsNever(L))
|
||||
? []
|
||||
: types
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromUnion
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromUnion<Types extends TSchema[], Key extends PropertyKey> = (
|
||||
TUnionEvaluated<TFromUnionRest<TFromRest<Types, Key>>>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromUnion<Types extends TSchema[], Key extends PropertyKey>(types: [...Types], key: Key): TFromUnion<Types, Key> {
|
||||
return (
|
||||
UnionEvaluated(FromUnionRest(FromRest(types as TSchema[], key)))
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromTuple
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromTuple<Types extends TSchema[], Key extends PropertyKey> = (
|
||||
Key extends keyof Types ? Types[Key] :
|
||||
Key extends '[number]' ? TUnionEvaluated<Types> :
|
||||
TNever
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromTuple<Types extends TSchema[], Key extends PropertyKey>(types: [...Types], key: Key): TFromTuple<Types, Key> {
|
||||
return (
|
||||
key in types ? types[key as number] :
|
||||
key === '[number]' ? UnionEvaluated(types) :
|
||||
Never()
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromArray
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromArray<Type extends TSchema, Key extends PropertyKey> = (
|
||||
Key extends '[number]'
|
||||
? Type
|
||||
: TNever
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromArray<Type extends TSchema, Key extends PropertyKey>(type: Type, key: Key): TFromArray<Type, Key> {
|
||||
return (
|
||||
key === '[number]'
|
||||
? type
|
||||
: Never()
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperty
|
||||
// ------------------------------------------------------------------
|
||||
type AssertPropertyKey<T> = Assert<T, string | number>
|
||||
|
||||
// prettier-ignore
|
||||
type TFromProperty<Properties extends TProperties, Key extends PropertyKey> = (
|
||||
// evaluate for string keys
|
||||
Key extends keyof Properties
|
||||
? Properties[Key]
|
||||
// evaluate for numeric keys
|
||||
: `${AssertPropertyKey<Key>}` extends `${AssertPropertyKey<keyof Properties>}`
|
||||
? Properties[AssertPropertyKey<Key>]
|
||||
: TNever
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromProperty<Properties extends TProperties, Key extends PropertyKey>(properties: Properties, propertyKey: Key): TFromProperty<Properties, Key> {
|
||||
return (propertyKey in properties ? properties[propertyKey as string] : Never()) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromKey
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TIndexFromPropertyKey<Type extends TSchema, Key extends PropertyKey> = (
|
||||
Type extends TRecursive<infer Type extends TSchema> ? TIndexFromPropertyKey<Type, Key> :
|
||||
Type extends TIntersect<infer Types extends TSchema[]> ? TFromIntersect<Types, Key> :
|
||||
Type extends TUnion<infer Types extends TSchema[]> ? TFromUnion<Types, Key> :
|
||||
Type extends TTuple<infer Types extends TSchema[]> ? TFromTuple<Types, Key> :
|
||||
Type extends TArray<infer Type extends TSchema> ? TFromArray<Type, Key> :
|
||||
Type extends TObject<infer Properties extends TProperties> ? TFromProperty<Properties, Key> :
|
||||
TNever
|
||||
)
|
||||
// prettier-ignore
|
||||
export function IndexFromPropertyKey<Type extends TSchema, Key extends PropertyKey>(type: Type, propertyKey: Key): TIndexFromPropertyKey<Type, Key> {
|
||||
return (
|
||||
IsIntersect(type) ? FromIntersect(type.allOf, propertyKey) :
|
||||
IsUnion(type) ? FromUnion(type.anyOf, propertyKey) :
|
||||
IsTuple(type) ? FromTuple(type.items ?? [], propertyKey) :
|
||||
IsArray(type) ? FromArray(type.items, propertyKey) :
|
||||
IsObject(type) ? FromProperty(type.properties, propertyKey) :
|
||||
Never()
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromKeys
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TIndexFromPropertyKeys<Type extends TSchema, PropertyKeys extends PropertyKey[], Result extends TSchema[] = []> = (
|
||||
PropertyKeys extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]]
|
||||
? TIndexFromPropertyKeys<Type, Right, [...Result, Assert<TIndexFromPropertyKey<Type, Left>, TSchema>]>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
export function IndexFromPropertyKeys<Type extends TSchema, PropertyKeys extends PropertyKey[]>(type: Type, propertyKeys: [...PropertyKeys]): TIndexFromPropertyKeys<Type, PropertyKeys> {
|
||||
return propertyKeys.map(propertyKey => IndexFromPropertyKey(type, propertyKey)) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromSchema
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type FromSchema<Type extends TSchema, PropertyKeys extends PropertyKey[]> = (
|
||||
TUnionEvaluated<TIndexFromPropertyKeys<Type, PropertyKeys>>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromSchema<Type extends TSchema, PropertyKeys extends PropertyKey[]>(type: Type, propertyKeys: [...PropertyKeys]): FromSchema<Type, PropertyKeys> {
|
||||
return (
|
||||
UnionEvaluated(IndexFromPropertyKeys(type, propertyKeys as PropertyKey[]))
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromSchema
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TIndexFromComputed<Type extends TSchema, Key extends TSchema> = (
|
||||
TComputed<'Index', [Type, Key]>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function IndexFromComputed<Type extends TSchema, Key extends TSchema>(type: Type, key: Key): TIndexFromComputed<Type, Key> {
|
||||
return Computed('Index', [type, key])
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TIndex
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TIndex<Type extends TSchema, PropertyKeys extends PropertyKey[]> = (
|
||||
FromSchema<Type, PropertyKeys>
|
||||
)
|
||||
/** `[Json]` Returns an Indexed property type for the given keys */
|
||||
export function Index<Type extends TRef, Key extends TSchema>(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed<Type, Key>
|
||||
/** `[Json]` Returns an Indexed property type for the given keys */
|
||||
export function Index<Type extends TSchema, Key extends TRef>(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed<Type, Key>
|
||||
/** `[Json]` Returns an Indexed property type for the given keys */
|
||||
export function Index<Type extends TRef, Key extends TRef>(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed<Type, Key>
|
||||
/** `[Json]` Returns an Indexed property type for the given keys */
|
||||
export function Index<Type extends TSchema, MappedResult extends TMappedResult>(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TIndexFromMappedResult<Type, MappedResult>
|
||||
/** `[Json]` Returns an Indexed property type for the given keys */
|
||||
export function Index<Type extends TSchema, MappedResult extends TMappedResult>(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TIndexFromMappedResult<Type, MappedResult>
|
||||
/** `[Json]` Returns an Indexed property type for the given keys */
|
||||
export function Index<Type extends TSchema, MappedKey extends TMappedKey>(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TIndexFromMappedKey<Type, MappedKey>
|
||||
/** `[Json]` Returns an Indexed property type for the given keys */
|
||||
export function Index<Type extends TSchema, Key extends TSchema, PropertyKeys extends PropertyKey[] = TIndexPropertyKeys<Key>>(T: Type, K: Key, options?: SchemaOptions): TIndex<Type, PropertyKeys>
|
||||
/** `[Json]` Returns an Indexed property type for the given keys */
|
||||
export function Index<Type extends TSchema, PropertyKeys extends PropertyKey[]>(type: Type, propertyKeys: readonly [...PropertyKeys], options?: SchemaOptions): TIndex<Type, PropertyKeys>
|
||||
/** `[Json]` Returns an Indexed property type for the given keys */
|
||||
export function Index(type: TSchema, key: any, options?: SchemaOptions): any {
|
||||
// computed-type
|
||||
if (IsRef(type) || IsRef(key)) {
|
||||
const error = `Index types using Ref parameters require both Type and Key to be of TSchema`
|
||||
if (!IsSchema(type) || !IsSchema(key)) throw new TypeBoxError(error)
|
||||
return Computed('Index', [type, key])
|
||||
}
|
||||
// mapped-types
|
||||
if (IsMappedResult(key)) return IndexFromMappedResult(type, key, options)
|
||||
if (IsMappedKey(key)) return IndexFromMappedKey(type, key, options)
|
||||
// prettier-ignore
|
||||
return CreateType(
|
||||
IsSchema(key)
|
||||
? FromSchema(type, IndexPropertyKeys(key))
|
||||
: FromSchema(type, key as string[])
|
||||
, options) as never
|
||||
}
|
||||
29
src/type/instance-type/index.ts
Normal file
29
src/type/instance-type/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './instance-type'
|
||||
45
src/type/instance-type/instance-type.ts
Normal file
45
src/type/instance-type/instance-type.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import { type TSchema, SchemaOptions } from '../schema/index'
|
||||
import { type TConstructor } from '../constructor/index'
|
||||
import { type TNever, Never } from '../never/index'
|
||||
import * as KindGuard from '../guard/kind'
|
||||
|
||||
// prettier-ignore
|
||||
export type TInstanceType<Type extends TSchema,
|
||||
Result extends TSchema = Type extends TConstructor<infer _Parameters extends TSchema[], infer InstanceType extends TSchema>
|
||||
? InstanceType
|
||||
: TNever
|
||||
> = Result
|
||||
|
||||
/** `[JavaScript]` Extracts the InstanceType from the given Constructor type */
|
||||
export function InstanceType<Type extends TSchema>(schema: Type, options?: SchemaOptions): TInstanceType<Type> {
|
||||
return (KindGuard.IsConstructor(schema) ? CreateType(schema.returns, options) : Never(options)) as never
|
||||
}
|
||||
29
src/type/instantiate/index.ts
Normal file
29
src/type/instantiate/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './instantiate'
|
||||
307
src/type/instantiate/instantiate.ts
Normal file
307
src/type/instantiate/instantiate.ts
Normal file
@@ -0,0 +1,307 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CloneType } from '../clone/type'
|
||||
import { type TSchema } from '../schema/index'
|
||||
import { type TArgument } from '../argument/index'
|
||||
import { type TUnknown, Unknown } from '../unknown/index'
|
||||
import { type TReadonlyOptional, ReadonlyOptional } from '../readonly-optional/index'
|
||||
import { type TReadonly, Readonly } from '../readonly/index'
|
||||
import { type TOptional, Optional } from '../optional/index'
|
||||
import { type TConstructor } from '../constructor/index'
|
||||
import { type TFunction } from '../function/index'
|
||||
import { type TIntersect } from '../intersect/index'
|
||||
import { type TUnion } from '../union/index'
|
||||
import { type TTuple } from '../tuple/index'
|
||||
import { type TArray } from '../array/index'
|
||||
import { type TAsyncIterator } from '../async-iterator/index'
|
||||
import { type TIterator } from '../iterator/index'
|
||||
import { type TPromise } from '../promise/index'
|
||||
import { type TObject, type TProperties, Object } from '../object/index'
|
||||
import { type TRecordOrObject, type TRecord, Record, RecordKey, RecordValue } from '../record/index'
|
||||
|
||||
import * as ValueGuard from '../guard/value'
|
||||
import * as KindGuard from '../guard/kind'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromConstructor<Args extends TSchema[], Parameters extends TSchema[], InstanceType extends TSchema,
|
||||
Result extends TConstructor = TConstructor<TFromTypes<Args, Parameters>, TFromType<Args, InstanceType>>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromConstructor(args: TSchema[], type: TConstructor): TConstructor {
|
||||
type.parameters = FromTypes(args, type.parameters)
|
||||
type.returns = FromType(args, type.returns)
|
||||
return type
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Function
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromFunction<Args extends TSchema[], Parameters extends TSchema[], ReturnType extends TSchema,
|
||||
Result extends TFunction = TFunction<TFromTypes<Args, Parameters>, TFromType<Args, ReturnType>>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromFunction(args: TSchema[], type: TFunction): TFunction {
|
||||
type.parameters = FromTypes(args, type.parameters)
|
||||
type.returns = FromType(args, type.returns)
|
||||
return type
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Intersect
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromIntersect<Args extends TSchema[], Types extends TSchema[],
|
||||
Result extends TIntersect = TIntersect<TFromTypes<Args, Types>>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromIntersect(args: TSchema[], type: TIntersect): TIntersect {
|
||||
type.allOf = FromTypes(args, type.allOf)
|
||||
return type
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Union
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromUnion<Args extends TSchema[], Types extends TSchema[],
|
||||
Result extends TUnion = TUnion<TFromTypes<Args, Types>>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromUnion(args: TSchema[], type: TUnion): TUnion {
|
||||
type.anyOf = FromTypes(args, type.anyOf)
|
||||
return type
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Tuple
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromTuple<Args extends TSchema[], Types extends TSchema[],
|
||||
Result extends TTuple = TTuple<TFromTypes<Args, Types>>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromTuple(args: TSchema[], type: TTuple): TTuple {
|
||||
if(ValueGuard.IsUndefined(type.items)) return type
|
||||
type.items = FromTypes(args, type.items!)
|
||||
return type
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Array
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromArray<Args extends TSchema[], Type extends TSchema,
|
||||
Result extends TArray = TArray<TFromType<Args, Type>>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromArray(args: TSchema[], type: TArray): TArray {
|
||||
type.items = FromType(args, type.items)
|
||||
return type
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// AsyncIterator
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromAsyncIterator<Args extends TSchema[], Type extends TSchema,
|
||||
Result extends TAsyncIterator = TAsyncIterator<TFromType<Args, Type>>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromAsyncIterator(args: TSchema[], type: TAsyncIterator): TAsyncIterator {
|
||||
type.items = FromType(args, type.items)
|
||||
return type
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Iterator
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromIterator<Args extends TSchema[], Type extends TSchema,
|
||||
Result extends TIterator = TIterator<TFromType<Args, Type>>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromIterator(args: TSchema[], type: TIterator): TIterator {
|
||||
type.items = FromType(args, type.items)
|
||||
return type
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Promise
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromPromise<Args extends TSchema[], Type extends TSchema,
|
||||
Result extends TPromise = TPromise<TFromType<Args, Type>>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromPromise(args: TSchema[], type: TPromise): TPromise {
|
||||
type.item = FromType(args, type.item)
|
||||
return type
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Object
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromObject<Args extends TSchema[], Properties extends TProperties,
|
||||
MappedProperties extends TProperties = TFromProperties<Args, Properties>,
|
||||
Result extends TSchema = TObject<MappedProperties>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromObject(args: TSchema[], type: TObject): TObject {
|
||||
const mappedProperties = FromProperties(args, type.properties)
|
||||
return { ...type, ...Object(mappedProperties) } // retain options
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Object
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromRecord<Args extends TSchema[], Key extends TSchema, Value extends TSchema,
|
||||
MappedKey extends TSchema = TFromType<Args, Key>,
|
||||
MappedValue extends TSchema = TFromType<Args, Value>,
|
||||
Result extends TSchema = TRecordOrObject<MappedKey, MappedValue>
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromRecord(args: TSchema[], type: TRecord): TRecord {
|
||||
const mappedKey = FromType(args, RecordKey(type))
|
||||
const mappedValue = FromType(args, RecordValue(type))
|
||||
const result = Record(mappedKey, mappedValue)
|
||||
return { ...type, ... result } as never // retain options
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Argument
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromArgument<Args extends TSchema[], Index extends number,
|
||||
Result extends TSchema = Index extends keyof Args[Index] ? Args[Index] : TUnknown
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromArgument(args: TSchema[], argument: TArgument): TSchema {
|
||||
return argument.index in args ? args[argument.index] : Unknown()
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Property
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperty<Args extends TSchema[], Type extends TSchema,
|
||||
IsReadonly extends boolean = Type extends TReadonly<Type> ? true : false,
|
||||
IsOptional extends boolean = Type extends TOptional<Type> ? true : false,
|
||||
Mapped extends TSchema = TFromType<Args, Type>,
|
||||
Result extends TSchema = (
|
||||
[IsReadonly, IsOptional] extends [true, true] ? TReadonlyOptional<Mapped> :
|
||||
[IsReadonly, IsOptional] extends [true, false] ? TReadonly<Mapped> :
|
||||
[IsReadonly, IsOptional] extends [false, true] ? TOptional<Mapped> :
|
||||
Mapped
|
||||
)
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromProperty<Args extends TSchema[], Type extends TSchema>(args: [...Args], type: Type): TFromProperty<Args, Type> {
|
||||
const isReadonly = KindGuard.IsReadonly(type)
|
||||
const isOptional = KindGuard.IsOptional(type)
|
||||
const mapped = FromType(args, type)
|
||||
return (
|
||||
isReadonly && isOptional ? ReadonlyOptional(mapped) :
|
||||
isReadonly && !isOptional ? Readonly(mapped) :
|
||||
!isReadonly && isOptional ? Optional(mapped) :
|
||||
mapped
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Properties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperties<Args extends TSchema[], Properties extends TProperties,
|
||||
Result extends TProperties = {
|
||||
[Key in keyof Properties]: TFromProperty<Args, Properties[Key]>
|
||||
}
|
||||
> = Result
|
||||
// prettier-ignore
|
||||
function FromProperties<Args extends TSchema[], Properties extends TProperties>(args: TSchema[], properties: TProperties): TFromProperties<Args, Properties> {
|
||||
return globalThis.Object.getOwnPropertyNames(properties).reduce((result, key) => {
|
||||
return { ...result, [key]: FromProperty(args, properties[key]) }
|
||||
}, {}) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Types
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TFromTypes<Args extends TSchema[], Types extends TSchema[], Result extends TSchema[] = []> = (
|
||||
Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]]
|
||||
? TFromTypes<Args, Right, [...Result, TFromType<Args, Left>]>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
export function FromTypes<Args extends TSchema[], Types extends TSchema[]>(args: [...Args], types: [...Types]): TFromTypes<Args, Types> {
|
||||
return types.map(type => FromType(args, type)) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Type
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TFromType<Args extends TSchema[], Type extends TSchema> = (
|
||||
Type extends TConstructor<infer Parameters extends TSchema[], infer InstanceType extends TSchema> ? TFromConstructor<Args, Parameters, InstanceType> :
|
||||
Type extends TFunction<infer Parameters extends TSchema[], infer ReturnType extends TSchema> ? TFromFunction<Args, Parameters, ReturnType> :
|
||||
Type extends TIntersect<infer Types extends TSchema[]> ? TFromIntersect<Args, Types> :
|
||||
Type extends TUnion<infer Types extends TSchema[]> ? TFromUnion<Args, Types> :
|
||||
Type extends TTuple<infer Types extends TSchema[]> ? TFromTuple<Args, Types> :
|
||||
Type extends TArray<infer Type extends TSchema> ? TFromArray<Args, Type>:
|
||||
Type extends TAsyncIterator<infer Type extends TSchema> ? TFromAsyncIterator<Args, Type> :
|
||||
Type extends TIterator<infer Type extends TSchema> ? TFromIterator<Args, Type> :
|
||||
Type extends TPromise<infer Type extends TSchema> ? TFromPromise<Args, Type> :
|
||||
Type extends TObject<infer Properties extends TProperties> ? TFromObject<Args, Properties> :
|
||||
Type extends TRecord<infer Key extends TSchema, infer Value extends TSchema> ? TFromRecord<Args, Key, Value> :
|
||||
Type extends TArgument<infer Index extends number> ? TFromArgument<Args, Index> :
|
||||
Type
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromType<Args extends TSchema[], Type extends TSchema>(args: [...Args], type: TSchema): TFromType<Args, Type> {
|
||||
return (
|
||||
KindGuard.IsConstructor(type) ? FromConstructor(args, type) :
|
||||
KindGuard.IsFunction(type) ? FromFunction(args, type) :
|
||||
KindGuard.IsIntersect(type) ? FromIntersect(args, type) :
|
||||
KindGuard.IsUnion(type) ? FromUnion(args, type) :
|
||||
KindGuard.IsTuple(type) ? FromTuple(args, type) :
|
||||
KindGuard.IsArray(type) ? FromArray(args, type) :
|
||||
KindGuard.IsAsyncIterator(type) ? FromAsyncIterator(args, type) :
|
||||
KindGuard.IsIterator(type) ? FromIterator(args, type) :
|
||||
KindGuard.IsPromise(type) ? FromPromise(args, type) :
|
||||
KindGuard.IsObject(type) ? FromObject(args, type):
|
||||
KindGuard.IsRecord(type) ? FromRecord(args, type) :
|
||||
KindGuard.IsArgument(type) ? FromArgument(args, type) :
|
||||
type
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Instantiate
|
||||
// ------------------------------------------------------------------
|
||||
/** `[JavaScript]` Instantiates a type with the given parameters */
|
||||
// prettier-ignore
|
||||
export type TInstantiate<Type extends TSchema, Args extends TSchema[],
|
||||
Result extends TSchema = TFromType<Args, Type>
|
||||
> = Result
|
||||
|
||||
/** `[JavaScript]` Instantiates a type with the given parameters */
|
||||
// prettier-ignore
|
||||
export function Instantiate<Type extends TSchema, Args extends TSchema[]>(type: Type, args: [...Args]): TInstantiate<Type, Args> {
|
||||
return FromType(args, CloneType(type))
|
||||
}
|
||||
29
src/type/integer/index.ts
Normal file
29
src/type/integer/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './integer'
|
||||
48
src/type/integer/integer.ts
Normal file
48
src/type/integer/integer.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
export interface IntegerOptions extends SchemaOptions {
|
||||
exclusiveMaximum?: number
|
||||
exclusiveMinimum?: number
|
||||
maximum?: number
|
||||
minimum?: number
|
||||
multipleOf?: number
|
||||
}
|
||||
export interface TInteger extends TSchema, IntegerOptions {
|
||||
[Kind]: 'Integer'
|
||||
static: number
|
||||
type: 'integer'
|
||||
}
|
||||
/** `[Json]` Creates an Integer type */
|
||||
export function Integer(options?: IntegerOptions): TInteger {
|
||||
return CreateType({ [Kind]: 'Integer', type: 'integer' }, options) as never
|
||||
}
|
||||
31
src/type/intersect/index.ts
Normal file
31
src/type/intersect/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './intersect-evaluated'
|
||||
export * from './intersect-type'
|
||||
export * from './intersect'
|
||||
52
src/type/intersect/intersect-create.ts
Normal file
52
src/type/intersect/intersect-create.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { CreateType } from '../create/type'
|
||||
import type { TSchema } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
import type { TIntersect, IntersectOptions } from './intersect-type'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsObject, IsSchema } from '../guard/kind'
|
||||
// ------------------------------------------------------------------
|
||||
// IntersectCreate
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export function IntersectCreate<T extends TSchema[]>(T: [...T], options: IntersectOptions = {}): TIntersect<T> {
|
||||
const allObjects = T.every((schema) => IsObject(schema))
|
||||
const clonedUnevaluatedProperties = IsSchema(options.unevaluatedProperties)
|
||||
? { unevaluatedProperties: options.unevaluatedProperties }
|
||||
: {}
|
||||
return CreateType(
|
||||
(options.unevaluatedProperties === false || IsSchema(options.unevaluatedProperties) || allObjects
|
||||
? { ...clonedUnevaluatedProperties, [Kind]: 'Intersect', type: 'object', allOf: T }
|
||||
: { ...clonedUnevaluatedProperties, [Kind]: 'Intersect', allOf: T })
|
||||
, options) as never
|
||||
}
|
||||
122
src/type/intersect/intersect-evaluated.ts
Normal file
122
src/type/intersect/intersect-evaluated.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import type { SchemaOptions, TSchema } from '../schema/index'
|
||||
import { OptionalKind } from '../symbols/index'
|
||||
import { CreateType } from '../create/type'
|
||||
import { Discard } from '../discard/index'
|
||||
import { Never, type TNever } from '../never/index'
|
||||
import { Optional, type TOptional } from '../optional/index'
|
||||
import type { TReadonly } from '../readonly/index'
|
||||
|
||||
import { TIntersect, IntersectOptions } from './intersect-type'
|
||||
import { IntersectCreate } from './intersect-create'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsOptional, IsTransform } from '../guard/kind'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// IsIntersectOptional
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TIsIntersectOptional<Types extends TSchema[]> = (
|
||||
Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]]
|
||||
? Left extends TOptional<TSchema>
|
||||
? TIsIntersectOptional<Right>
|
||||
: false
|
||||
: true
|
||||
)
|
||||
// prettier-ignore
|
||||
function IsIntersectOptional<Types extends TSchema[]>(types: [...Types]): TIsIntersectOptional<Types> {
|
||||
return types.every(left => IsOptional(left)) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// RemoveOptionalFromType
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TRemoveOptionalFromType<Type extends TSchema> = (
|
||||
Type extends TReadonly<infer Type extends TSchema> ? TReadonly<TRemoveOptionalFromType<Type>> :
|
||||
Type extends TOptional<infer Type extends TSchema> ? TRemoveOptionalFromType<Type> :
|
||||
Type
|
||||
)
|
||||
// prettier-ignore
|
||||
function RemoveOptionalFromType<Type extends TSchema>(type: Type): TRemoveOptionalFromType<Type> {
|
||||
return (
|
||||
Discard(type, [OptionalKind])
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// RemoveOptionalFromRest
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TRemoveOptionalFromRest<Types extends TSchema[], Result extends TSchema[] = []> = (
|
||||
Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]]
|
||||
? Left extends TOptional<infer Type extends TSchema>
|
||||
? TRemoveOptionalFromRest<Right, [...Result, TRemoveOptionalFromType<Type>]>
|
||||
: TRemoveOptionalFromRest<Right, [...Result, Left]>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
function RemoveOptionalFromRest<Types extends TSchema[]>(types: [...Types]): TRemoveOptionalFromRest<Types> {
|
||||
return types.map(left => IsOptional(left) ? RemoveOptionalFromType(left) : left) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ResolveIntersect
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TResolveIntersect<Types extends TSchema[]> = (
|
||||
TIsIntersectOptional<Types> extends true
|
||||
? TOptional<TIntersect<TRemoveOptionalFromRest<Types>>>
|
||||
: TIntersect<TRemoveOptionalFromRest<Types>>
|
||||
)
|
||||
// prettier-ignore
|
||||
function ResolveIntersect<Types extends TSchema[]>(types: [...Types], options: SchemaOptions): TResolveIntersect<Types> {
|
||||
return (
|
||||
IsIntersectOptional(types)
|
||||
? Optional(IntersectCreate(RemoveOptionalFromRest(types) as TSchema[], options))
|
||||
: IntersectCreate(RemoveOptionalFromRest(types) as TSchema[], options)
|
||||
) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// IntersectEvaluated
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TIntersectEvaluated<Types extends TSchema[]> = (
|
||||
Types extends [TSchema] ? Types[0] :
|
||||
Types extends [] ? TNever :
|
||||
TResolveIntersect<Types>
|
||||
)
|
||||
/** `[Json]` Creates an evaluated Intersect type */
|
||||
export function IntersectEvaluated<Types extends TSchema[], Result extends TSchema = TIntersectEvaluated<Types>>(types: [...Types], options: IntersectOptions = {}): Result {
|
||||
if (types.length === 1) return CreateType(types[0], options) as never
|
||||
if (types.length === 0) return Never(options) as never
|
||||
if (types.some((schema) => IsTransform(schema))) throw new Error('Cannot intersect transform types')
|
||||
return ResolveIntersect(types, options) as never
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user