/** @module evolve-type.ts */ import { AnyFunction, AnyObject, ContainsAny, ContainsType, ExtractFunctionArguments, ExtractFunctionReturnValue, IsAny, KeySubset } from '../helper-types' type EvolvingValueNotAFunction = T // 'THE VALUE ON THE LEFT HAND SIDE NEEDS TO BE A FUNCTION, OBJECT, OR ARRAY' type BadEvolve = 'ERROR: Evolving / left-side function argument type does not match right-side corresponding value type' type WrongKeys = 'ERROR: All keys on the type for the left-side object must be in the right-side object' type Evolve10 = { 'evaluate': ContainsType<[E, I], {}> extends true ? {} : { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? IsAny[0]> extends true ? ExtractFunctionReturnValue : [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : E[K] extends number | string | symbol | any[] ? EvolvingValueNotAFunction : Evolve10< E[ K ], I[ K ]> : I[K] } 'done': ContainsAny < [ E, I], {}, WrongKeys>, }[ KeySubset < E, I > extends true ? 'evaluate' : 'done' ] type Evolve9 = { 'evaluate': ContainsType<[E, I], {}> extends true ? {} : { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? IsAny[0]> extends true ? ExtractFunctionReturnValue : [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : E[K] extends number | string | symbol ? EvolvingValueNotAFunction : Evolve10< E[ K ], I[ K ]> : I[K] } 'done': ContainsAny < [ E, I], {}, WrongKeys>, }[ KeySubset < E, I > extends true ? 'evaluate' : 'done' ] type Evolve8 = { 'evaluate': ContainsType<[E, I], {}> extends true ? {} : { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? IsAny[0]> extends true ? ExtractFunctionReturnValue : [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : E[K] extends number | string | symbol ? EvolvingValueNotAFunction : Evolve9< E[ K ], I[ K ]> : I[K] } 'done': ContainsAny < [ E, I], {}, WrongKeys>, }[ KeySubset < E, I > extends true ? 'evaluate' : 'done' ] type Evolve7 = { 'evaluate': ContainsType<[E, I], {}> extends true ? {} : { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? IsAny[0]> extends true ? ExtractFunctionReturnValue : [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : E[K] extends number | string | symbol ? EvolvingValueNotAFunction : Evolve8< E[ K ], I[ K ]> : I[K] } 'done': ContainsAny < [ E, I], {}, WrongKeys>, }[ KeySubset < E, I > extends true ? 'evaluate' : 'done' ] type Evolve6 = { 'evaluate': ContainsType<[E, I], {}> extends true ? {} : { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? IsAny[0]> extends true ? ExtractFunctionReturnValue : [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : E[K] extends number | string | symbol ? EvolvingValueNotAFunction : Evolve7< E[ K ], I[ K ]> : I[K] } 'done': ContainsAny < [ E, I], {}, WrongKeys>, }[ KeySubset < E, I > extends true ? 'evaluate' : 'done' ] type Evolve5 = { 'evaluate': ContainsType<[E, I], {}> extends true ? {} : { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? IsAny[0]> extends true ? ExtractFunctionReturnValue : [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : E[K] extends number | string | symbol ? EvolvingValueNotAFunction : Evolve6< E[ K ], I[ K ]> : I[K] } 'done': ContainsAny < [ E, I], {}, WrongKeys>, }[ KeySubset < E, I > extends true ? 'evaluate' : 'done' ] type Evolve4 = { 'evaluate': ContainsType<[E, I], {}> extends true ? {} : { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? IsAny[0]> extends true ? ExtractFunctionReturnValue : [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : E[K] extends number | string | symbol ? EvolvingValueNotAFunction : Evolve5< E[ K ], I[ K ]> : I[K] } 'done': ContainsAny < [ E, I], {}, WrongKeys>, }[ KeySubset < E, I > extends true ? 'evaluate' : 'done' ] type Evolve3 = { 'evaluate': ContainsType<[E, I], {}> extends true ? {} : { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? IsAny[0]> extends true ? ExtractFunctionReturnValue : [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : E[K] extends number | string | symbol ? EvolvingValueNotAFunction : Evolve4< E[ K ], I[ K ]> : I[K] } 'done': ContainsAny < [ E, I], {}, WrongKeys>, }[ KeySubset < E, I > extends true ? 'evaluate' : 'done' ] type Evolve2 = { 'evaluate': ContainsType<[E, I], {}> extends true ? {} : { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? IsAny[0]> extends true ? ExtractFunctionReturnValue : [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : E[K] extends number | string | symbol ? EvolvingValueNotAFunction : Evolve3< E[ K ], I[ K ]> : I[K] } 'done': ContainsAny < [ E, I], {}, WrongKeys>, }[ KeySubset < E, I > extends true ? 'evaluate' : 'done' ] // Lazy evaluated to prevent hangups export type Evolve = { 'evaluate': ContainsType<[E, I], {}> extends true ? {} : { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? IsAny[0]> extends true ? ExtractFunctionReturnValue : [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : E[K] extends number | string | symbol ? EvolvingValueNotAFunction : Evolve2< E[ K ], I[ K ]> : I[K] } 'done': ContainsAny < [ E, I], {}, WrongKeys>, }[ KeySubset < E, I > extends true ? 'evaluate' : 'done' ] // straight-foward recursion export type EvolveRecursive[0] > = KeySubset < E, I > extends true ? { [ K in keyof I ]: K extends keyof E ? E[K] extends AnyFunction ? [I[K]] extends ExtractFunctionArguments ? ExtractFunctionReturnValue : BadEvolve : EvolveRecursive< E[ K ], I[ K ]> : I[K] } : ContainsAny < [ E, I ], {}, WrongKeys >