diff --git a/examples/index.ts b/examples/index.ts index 576a0b569..de220bb85 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -2,22 +2,18 @@ // Accessor // -------------------------------------------------------------------------- -import { Type, Optional, TOptional, TReadonly, TObject, TTuple, TIntersect, TUnion, Kind, TSchema, TypeClone, TypeGuard, ValueGuard, TPropertyKey, SchemaOptions, TProperties, TNever, TRecursive, TArray, Discard, TNumber, TString, TBoolean } from "@sinclair/typebox" - -export function Into(func: () => T): T { - return func() -} +import { Type, Static, Distinct, Optional, TOptional, TReadonly, TObject, TTuple, TIntersect, TUnion, Kind, TSchema, TypeClone, TypeGuard, ValueGuard, TPropertyKey, SchemaOptions, TProperties, TNever, TRecursive, TArray, Discard, TNumber, TString, TBoolean } from "@sinclair/typebox" const T = Type.Object({ - x: Type.String(), - y: Type.Union([ - Type.Number(), - Type.BigInt() - ]) + x: Type.Number(), + y: Type.Number(), + z: Type.Number() }) +type T = typeof T -const I = Type.Index(T, Type.KeyOf(T)) - +type A = Distinct.Resolve<[TString, T]> +const A = Distinct.Resolve([Type.String(), T]) +console.log(A) // ------------------------------------------------------------------ // Accessor diff --git a/src/typebox.ts b/src/typebox.ts index 5fff06553..c39b8ece4 100644 --- a/src/typebox.ts +++ b/src/typebox.ts @@ -2434,31 +2434,40 @@ export namespace TypeClone { // Distinct // ------------------------------------------------------------------ // prettier-ignore -export type TDistinctIncludes = - T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? C extends L - ? true - : TDistinctIncludes - : false -// prettier-ignore -export type TDistinct = - T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? TDistinctIncludes extends false - ? TDistinct - : TDistinct - : Acc - export namespace Distinct { - function DistinctIncludes(schemas: TSchema[], candidate: TSchema) { - return schemas.find((schema) => TypeExtends.Extends(candidate, schema) === TypeExtendsResult.True) !== undefined + // ---------------------------------------------------------------- + // Includes + // ---------------------------------------------------------------- + export type Includes = + T extends [infer L extends TSchema, ...infer R extends TSchema[]] + ? C extends L + ? true + : Includes + : false + export function Includes(T: TSchema[], C: TSchema): boolean { + const [L, ...R] = T + return T.length > 0 + ? TypeExtends.Extends(C, L) === TypeExtendsResult.True + ? true + : Includes(R, C) + : false } - // prettier-ignore - export function Distinct(schemas: [...T]): TDistinct { - return schemas.reduce((acc, candidate) => { - return !DistinctIncludes(acc, candidate) - ? [...acc, candidate] - : [...acc] - }, [] as TSchema[]) as TDistinct + // ---------------------------------------------------------------- + // Resolve + // ---------------------------------------------------------------- + export type Resolve = + T extends [infer L extends TSchema, ...infer R extends TSchema[]] + ? Includes extends false + ? Resolve + : Resolve + : Acc + export function Resolve(T: TSchema[], Acc: TSchema[] = []): TSchema[] { + const [L, ...R] = T + return T.length > 0 + ? Includes(Acc, L) === false + ? Resolve(R, [...Acc, L]) + : Resolve(R, [...Acc]) + : Acc } } // --------------------------------------------------------------------------