@SHUPILOID

Как правильно реализовать дженерик?

У меня есть функция которя на входе принимает массив из объектво с ключами camelCase и переделывает на тот же массив только ключи меняе на snake_case.

const camelToSnakeKeysOfArrayObject = <
  T extends { [key: string]: unknown }[]
>(
  arr: { [key: string]: unknown }[]
): T =>
  arr.map(item =>
    Object.entries(item)
      .map(([key, value]) => ({
        [camelToSnakeCase(key)]: value,
      }))
      .reduce((acc, item) => ({ ...acc, ...item }), {})
  );


Я хочу что бы оно принимало тип массива с помощью generic. Но у меня вылетает ошибка
Type '{ [x: string]: unknown; }[]' is not assignable to type 'T'.
'{ [x: string]: unknown; }[]' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{ [key: string]: unknown; }[]'.


Подскажите пожалуйста как правильно реализовать
  • Вопрос задан
  • 165 просмотров
Решения вопроса 1
Aetae
@Aetae Куратор тега TypeScript
Тлен
typescriptlang.org/play
spoiler
type Alph = 'Q' | 'W' | 'E' | 'R' | 'T' | 'Y' | 'U' | 'I' | 'O' | 'P' | 'A' | 'S' | 'D' | 'F' | 'G' | 'H' | 'J' | 'K' | 'L' | 'X' | 'Z' | 'C' | 'V' | 'B' | 'N' | 'M'

type CamelToSnake<T extends string> = T extends `${infer S1}${Alph}${string}` ? T extends `${S1}${infer S2}` ? `${Lowercase<S1>}_${CamelToSnake<Uncapitalize<S2>>}` : T : T;
type AsdSnake = CamelToSnake<'asdAsdAsd'> // asd_asd_asd

type SnakeToCamel<T extends string> = T extends `${infer S1}_${infer S2}` ? `${Lowercase<S1>}${Capitalize<SnakeToCamel<S2>>}` : T;
type AsdCamel = SnakeToCamel<'asd_asd_asd'> // asdAsdAsd

type SnakePropToCamel<T extends PropertyKey> = T extends string ? SnakeToCamel<T> : T;
type CamelPropToSnake<T extends PropertyKey> = T extends string ? CamelToSnake<T> : T;

let camelToSnakeCase: <T extends PropertyKey>(str: T) => CamelPropToSnake<T>;

type CamelObjectToSnake<T extends {[key: string]: any}> = {
  [K in keyof T as CamelPropToSnake<K>]: T[K]
}

function camelCaseObject<T extends {[key: string]: any}>(obj: T) {
  return Object.entries(obj)
    .reduce((acc, [key, value]) =>
        (acc[camelToSnakeCase(key as keyof T)] = value, acc),
      {} as CamelObjectToSnake<T>
    )
}

function camelToSnakeKeysOfArrayObject<T extends Array<{[key: string]: any}>>(arr: T) {
  return arr.map(camelCaseObject) as {
    [K in keyof T]: CamelObjectToSnake<T[K]>
  };
}

Основано на варианте WbICHA но поддерживает объекты разных сигнатур, типа:
camelToSnakeKeysOfArrayObject([{
  aaAa: 1,
  bbBb: true
}, {
  aaAa: 'ggg'
}]);
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Alexandroppolus
@Alexandroppolus
кодир
Нужен ли здесь темплейт?

Может, будет достаточно
type Data = Array<Record<string, unknown>>;

const camelToSnakeKeysOfArrayObject = (arr: Data): Data => ...

?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы