UNPKG

@sinclair/typebox

Version:

Json Schema Type Builder with Static Type Resolution for TypeScript

92 lines (91 loc) 3.83 kB
import { CreateType } from '../create/type.mjs'; import { Computed } from '../computed/index.mjs'; import { Literal } from '../literal/index.mjs'; import { Never } from '../never/index.mjs'; import { IntersectEvaluated } from '../intersect/index.mjs'; import { UnionEvaluated } from '../union/index.mjs'; // ------------------------------------------------------------------ // Infrastructure // ------------------------------------------------------------------ import { IndexPropertyKeys } from './indexed-property-keys.mjs'; import { IndexFromMappedKey } from './indexed-from-mapped-key.mjs'; import { IndexFromMappedResult } from './indexed-from-mapped-result.mjs'; // ------------------------------------------------------------------ // KindGuard // ------------------------------------------------------------------ import { IsArray, IsIntersect, IsObject, IsMappedKey, IsMappedResult, IsNever, IsSchema, IsTuple, IsUnion, IsLiteralValue, IsRef } from '../guard/kind.mjs'; import { IsArray as IsArrayValue } from '../guard/value.mjs'; // prettier-ignore function FromRest(types, key) { return types.map(left => IndexFromPropertyKey(left, key)); } // prettier-ignore function FromIntersectRest(types) { return types.filter(left => !IsNever(left)); } // prettier-ignore function FromIntersect(types, key) { return (IntersectEvaluated(FromIntersectRest(FromRest(types, key)))); } // prettier-ignore function FromUnionRest(types) { return (types.some(L => IsNever(L)) ? [] : types); } // prettier-ignore function FromUnion(types, key) { return (UnionEvaluated(FromUnionRest(FromRest(types, key)))); } // prettier-ignore function FromTuple(types, key) { return (key === '[number]' ? UnionEvaluated(types) : key in types ? types[key] : Never()); } // prettier-ignore function FromArray(type, key) { // ... ? return (key === '[number]' ? type : Never()); } // prettier-ignore function FromProperty(properties, key) { return (key in properties ? properties[key] : Never()); } // prettier-ignore export function IndexFromPropertyKey(type, key) { return (IsIntersect(type) ? FromIntersect(type.allOf, key) : IsUnion(type) ? FromUnion(type.anyOf, key) : IsTuple(type) ? FromTuple(type.items ?? [], key) : IsArray(type) ? FromArray(type.items, key) : IsObject(type) ? FromProperty(type.properties, key) : Never()); } // prettier-ignore export function IndexFromPropertyKeys(type, propertyKeys) { return propertyKeys.map(left => IndexFromPropertyKey(type, left)); } // prettier-ignore function FromType(type, propertyKeys) { const result = IndexFromPropertyKeys(type, propertyKeys); return UnionEvaluated(result); } // prettier-ignore function UnionFromPropertyKeys(propertyKeys) { const result = propertyKeys.reduce((result, key) => IsLiteralValue(key) ? [...result, Literal(key)] : result, []); return UnionEvaluated(result); } /** `[Json]` Returns an Indexed property type for the given keys */ // prettier-ignore export function Index(type, key, options) { const typeKey = IsArrayValue(key) ? UnionFromPropertyKeys(key) : key; const propertyKeys = IsSchema(key) ? IndexPropertyKeys(key) : key; const isTypeRef = IsRef(type); const isKeyRef = IsRef(key); return (IsMappedResult(key) ? IndexFromMappedResult(type, key, options) : IsMappedKey(key) ? IndexFromMappedKey(type, key, options) : (isTypeRef && isKeyRef) ? Computed('Index', [type, typeKey], options) : (!isTypeRef && isKeyRef) ? Computed('Index', [type, typeKey], options) : (isTypeRef && !isKeyRef) ? Computed('Index', [type, typeKey], options) : CreateType(FromType(type, propertyKeys), options)); }