В машинописном тексте, как вы создаете индекс из вложенных ключей

Это не работает, но я хочу сделать что-то вроде этого:

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

так что ProxyNestedKeys могут быть проиндексированы вложенными свойствами O.

Например, если бы я создавал библиотеку проверки, которая делала следующее:

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
    }
  }
}

Итак, результат - это то, что я пытаюсь напечатать, и у меня это получилось:

// 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?
}

Мне не нужно рекурсивно получать все реквизиты еще на один уровень в глубину.


person Adrian Adkison    schedule 19.07.2019    source источник


Ответы (1)


Обновление предложенного вопроса

Что-то вроде этого

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);

Старый Анвевер

Я хотел бы написать что-то вроде этого

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;

Но TypeScript имеет некоторые ограничения для рекурсивных типов. Итак, есть обходной путь

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>>>>;
person Nail Achmedzhanov    schedule 19.07.2019
comment
Спасибо за ответ, Наиль! Мой вопрос был слишком расплывчатым, поэтому я сделал его немного яснее. Мне не нужно рекурсивное сглаживание. - person Adrian Adkison; 19.07.2019