1

This doesn't work but I want to do something like this:

type ProxyNestedKeys<O> = {
  [P in Extract<keyof O, string> Q in Extract<keyof O[P], string>]: boolean
}

so that ProxyNestedKeys can be indexed by nested properties of O.

For example if I was building a validation library that did the following:

const schema = {
  foo: {
    minVal: 2,
    maxVal: 5 
  }
}


const state = { foo: 6 }

const result = validate(schema, state)

// result
{
  foo: {
    $isValid: false
    $validations: {
      minVal: true
      maxVal: false
    }
  }
}

So the result is what I'm trying to type and I've got it this far:

// S is the state and V is the schema
type Validation<S, V> = {
  [K in Extract<keyof S, keyof V>]: Validation<S[K], V[K]>
} & {
  $isValid: boolean
  $validations: what goes here?
}

I don't need to recursively get all props just one more level deep.

0

1 Answer 1

1

Update for suggested qusetion

Something like this

const schema = {
  foo: {
    minVal: 2,
    maxVal: 5 
  }
}

type ValidationResult<S> = {
  [K in keyof S]: {[VK in keyof S[K]]: boolean} & {$isValid: boolean}
} 
const state = { foo: 6 }
declare function validate<S,V>(schema: S, value: V): ValidationResult<S>;
const result = validate(schema, state);

Old Anwever

I would like to write somethink like this

type FlattenByKeys<K extends keyof T, T> = K extends any ? 
  (T[K] extends object ? FlattenByKeys<keyof T[K], T[K]> : withKey<K, T[K]> ):
  never;

But TypeScript has some limitations for recursive types. So there is workaround

type WithKey<K extends string | number | symbol, T> = {
    [k in K]: T
}

type FlattenByKeys<K extends keyof T, T> = K extends any ? 
  (T[K] extends object ? {__r: FlattenByKeys<keyof T[K], T[K]>} : WithKey<K, T[K]> ):
  never;

type FR<T> = T extends {__r: infer U} ? U : T;
type FR10<T> = FR<FR<FR<FR<FR<FR<FR<FR<FR<FR<FR<T>>>>>>>>>>>;

type UnionToIntersection<U> = 
  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

type Pretty<T> = {
  [K in keyof T] : T[K]
}

const v = {
  a: 1,
  b: 2,
  c: {
    x: 1,
    y: 2,
    d: {
      l: '5',
      m: '6'
    }
  }
};

type V = typeof v;

/*

type Test = {
    a: number;
    b: number;
    x: number;
    y: number;
    l: string;
    m: string;
}

*/
type Test = Pretty<UnionToIntersection<FR10<FlattenByKeys<keyof V, V>>>>;
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the response Nail! My question was too vague so I made it a little clearer. I don't need recursive flattening.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.