Указание на конкретный тип в объекте, typescript

есть следующая функция - трансформер, написанная на Typescript. Во входном объекте я указываю объект - словарь, ru, en, ключи могут быть как просто строки, так и функции которые возвращают строки. В выходном объекте, хочу чтобы typescript указывал на тип конкретного поля, тайпскрипт указывает на все типы:

код:

const dictionary = {
 ru: {
  plainText: 'Простой текст',
  textFunction: (temp: number) => `Добавить +${temp}`
 },
 en: {
  plainText: 'Plain text',
  textFunction: (temp: number) => `Add +${temp}`
 }
}

const transformObject = <Obj extends Object = any, K extends keyof Obj = any>(
  obj: Obj,
) => {
  return (Object.keys(obj) as K[]).reduce((acc, translationKey) => {
    const translationObject = obj[translationKey];
    const translates = (
      Object.keys(translationObject) as Array<keyof Obj[K]>
    ).reduce((acc, langKey) => {
      return {
        ...acc,
        [langKey]: {
          [translationKey]: translationObject[langKey],
        },
      };
    }, {});
    return merge(acc, translates);
  }, {}) as {
    [Langs in keyof Obj[K]]: {
      [T in keyof Obj]: Obj[K][keyof Obj[K]];
    };
  };
};

const locales = transformObject(dictionary);

на выходе получаем следующую структуру:

/**
 * {
 *  ru: {
 *    plainText: string | (temp: number) => string;
 *    textFunction: string | (temp: number) => string;
 *  }
 *  en: {
 *    plainText: string | (temp: number) => string;
 *    textFunction: string | (temp: number) => string;
 *  }
 * }
 * 
 */

Хотелось бы получить это:

/*
 * {
 *  ru: {
 *    plainText: string;
 *    textFunction: (temp: number) => string;
 *  }
 *  en: {
 *    plainText: string
 *    textFunction: (temp: number) => string
 *  }
 * }
 * 
 */

Ответы (1 шт):

Автор решения: nörbörnën
type TTransformDictionary<T extends object> = {
  [K2 in keyof T[keyof T]]: { [K1 in keyof T]: T[K1][K2] }
};

const dictionary = {
 ru: {
  plainText: 'Простой текст',
  textFunction: (temp: number) => `Добавить +${temp}`
 },
 en: {
  plainText: 'Plain text',
  textFunction: (temp: number) => `Add +${temp}`
 }
};

const transformObject = <T extends object>(obj: T): TTransformDictionary<T> => {
  // your code here
  return null as unknown as TTransformDictionary<T>;
};

const locales = transformObject(dictionary);

Результат:

const locales: {
    plainText: {
        ru: string;
        en: string;
    };
    textFunction: {
        ru: (temp: number) => string;
        en: (temp: number) => string;
    };
}

Eсли вашу задачу (как я её понял) писать на настоящем typescript то код должен был бы быть таким. Обратите внимание на типизацию, сама транформация данных не так уж важна.

→ Ссылка