@hamster141095

Как преобразовать имена свойств объекта из kebab-case в camelCase?

Мне нужно переписать свою старую функцию согласно императивного подхода. Смысл функции - при получении данных с сервера все свойства объекта (как и вложенные) переименовывает из ке_баб в camelCase. Пример старой функции, все работало:
export const convertKeysToCamelCaseOrRemove = (
  responseData: { [key: string]: any },
  except?: Array<string>
) => {

      
  const keys =  Object.keys(responseData);
  keys.forEach((key) => {
    if (typeof responseData[key] === 'object' ) {
      convertKeysToCamelCaseOrRemove(responseData[key]);
    }
    const oldKeyArray: Array<string> | string = key.replace('__', '_').split('_');

    let newKeyArray: Array<string> = [];

    if (oldKeyArray.length === 1) {
      newKeyArray.push(oldKeyArray.toString());
    }
    const firstKeyWord: Array<string> = [];
    const restKeyWord: Array<string> = [];

    oldKeyArray.map((oldKey: string) => {
      if (oldKeyArray.indexOf(oldKey) === 0) {
        firstKeyWord.push(oldKey);
        return firstKeyWord;
      }
      const newKey = oldKey[0].toUpperCase() + oldKey.slice(1);
      restKeyWord.push(newKey);
      return restKeyWord;
    });

    newKeyArray = [...firstKeyWord, ...restKeyWord];
    const newKey = newKeyArray.join('');

    if (newKey !== key) {
      delete Object.assign(responseData, { [newKey]: responseData[key] })[key];
    }
    except &&
      except.forEach((exceptKey) => {
        if (newKey === exceptKey) {
          delete Object.assign(responseData)[exceptKey];
        }
      });



    return newKeyArray;
  });
  return responseData;
};

И новая:

export const convertKeysToCamelCaseOrRemove = (
  responseData: { [key: string]: any },
) => {

  const newArr = responseData &&  Object.entries(responseData).map((item) => {
    const key = item[0];
    const  value = item[1];


    if (typeof value === 'object' &&  value !== null &&  value !== undefined && value.length ) {
      value.map((item123:any) =>convertKeysToCamelCaseOrRemove(item123));
    }

    let arrKey =  key.replace('__', '_').split('_');
    if (arrKey.length > 1) {
      const first = arrKey[0];
      const old = arrKey.splice(1).map((oldKey => oldKey.charAt(0).toUpperCase() + oldKey.substring(1)));
      arrKey = [first, ...old];
    }
    return [arrKey.join(''), value];
  });


  return  Object.fromEntries(newArr);
  
};

Я как то неправильно делаю рекурсию.
  • Вопрос задан
  • 192 просмотра
Решения вопроса 2
0xD34F
@0xD34F
const toCamelCase = val =>
  val instanceof Array
    ? val.map(toCamelCase)
    : val instanceof Object
      ? Object.fromEntries(Object
          .entries(val)
          .map(n => [
            n[0].replace(/_+(.)/g, (m, g1) => g1.toUpperCase()),
            toCamelCase(n[1]),
          ])
        )
      : val;
Ответ написан
bingo347
@bingo347 Куратор тега TypeScript
Crazy on performance...
В дополнение к ответу 0xD34F нормальная типизация такой функции (нужен typescript 4.1 или выше):
type AsCamelCase<S extends string> = S extends `${infer A}_${infer B}` ? `${A}${Capitalize<AsCamelCase<B>>}` : S;
type CamelCaseKeysRecord<T> = T extends Record<PropertyKey, unknown> ? {
    [K in string & keyof T as AsCamelCase<K>]: CamelCaseKeysRecord<T[K]>;
} & {
    [K in Exclude<keyof T, string>]: CamelCaseKeysRecord<T[K]>;
} : T;

function toCamelCaseKeys<T>(val: T): CamelCaseKeysRecord<T> {
    if (Array.isArray(val)) {
        return val.map(toCamelCaseKeys) as unknown as CamelCaseKeysRecord<T>;
    }
    if (typeof val === 'object') {
        return Object.fromEntries(Object
            .entries(val)
            .map(([k, v]) => [
                k.replace(/_+(.)/g, (_, g) => g.toUpperCase()),
                toCamelCaseKeys(v as Record<string, unknown>),
            ])) as CamelCaseKeysRecord<T>;
    }
    return val as unknown as CamelCaseKeysRecord<T>;
}

https://www.typescriptlang.org/play?target=7&ts=4....
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@hamster141095 Автор вопроса
Изменил так, не работает при некоторых случаях
if (typeof value === 'object' &&  value !== null &&  value !== undefined && value.length ) {
      value = [...value.map((item1:any) => convertKeysToCamelCaseOrRemove(item1)
      )];
    }
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы