Я пишу функцию, которая принимает объект (A), сравнивает его с другим объектом (B) и создает новый объект (C). Объекты A и B симметричны (одинаковое количество свойств, одинаковые ключи), но тип их значений может различаться. Например: A.amount может быть «11», а B.amount — числом. Конечным результатом должен быть объект C, который имеет значения из A с типами из B.
В функции, которую я придумал, я перебираю все свойства объекта A, проверяя тип свойств объекта B с помощью оператора switch/case, применяя преобразование типов (например, .toString()) и добавляя исправленное свойство к объекту C. .
Я хотел бы, чтобы код был рекурсивным, но как только задействованы вложенные объекты, я не знаю, как получить свойства в B и создать эквивалент в C.
Пример объекта А:
const data = {
a: "15",
b: "foo",
c: false,
d: {
da: 99,
db: [{
dba: "1.2",
dbb: true
}]
}
}
Пример объекта B:
const targetType = {
a: 27,
b: "foofoo",
c: true,
d: {
da: "bar",
db: [{
dba: 4,
dbb: false
}]
}
}
Пример объекта C - значения из A, типы из B:
const finalObject = {
a: 15,
b: "foo",
c: false,
d: {
da: "99",
db: [{
dba: 1.2,
dbb: true
}]
}
}
Моя функция:
//data = object A
//targetType = object B
export function typeConversion(data: any, targetType: any) {
const resultObj = {};
Object.keys(data).forEach((key) => {
switch (typeof targetType[key]) {
case 'string':
resultObj[key] = data[key].toString();
break;
case 'boolean':
resultObj[key] = data[key] ? 'Yes' : 'No';
break;
case 'number':
resultObj[key] = Number(data[key]);
break;
//here is where it gets tricky:
case 'object':
if (Array.isArray(data[key])) {
const dataArray: any = [];
data[key].forEach((o) => {
//all objs in the array have the same shape, hence comparing to [0]
dataArray.push(typeConversion(o, targetType[key][0]));
});
resultObj[key] = dataArray;
} else {
const dataObj = {};
Object.keys(data[key]).forEach((subkey) => {
dataObj[subkey] = typeConversion(subkey, targetType[key][subkey]);
});
resultObj[key] = dataObj;
}
break;
}
});
return resultObj;
}
console.info(typeConversion(data, targetType))
В тот момент, когда есть вложенный объект и typeConversion вызывается рекурсивно, ему не удастся найти путь к свойству в объекте B. Я мог бы добавить необязательный параметр в функцию для «родительского свойства», но это будет работать только для одного уровень глубины.
Если есть способ сделать это рекурсивным, это не может быть путем кодирования пути к targetType[like][this].
Пример игровой площадки TypeScript
Приветствуются все идеи, возможно, я неправильно ко всему отношусь.
Спасибо за проверку, добавлены примеры всех объектов
Если это действительно вопрос TypeScript (а не вопрос JavaScript), то код примера полон ошибок, не связанных с вашей проблемой. Предоставьте минимальный воспроизводимый пример, который четко демонстрирует проблему, с которой вы столкнулись. В идеале кто-то мог бы вставить код в автономную IDE, такую как Площадка TypeScript (ссылка здесь!), и сразу же приступить к решению проблемы, не создавая ее заново. Таким образом, не должно быть псевдокода, опечаток, несвязанных ошибок или необъявленных типов или значений.
Добавлен пример детской площадки.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я внес некоторые изменения в вашу функцию, чтобы рекурсивно создать конечный объект. Хотя это не Typescript конкретная проблема, мне интересно, как это можно использовать :)
const transform = (data, targetType) => {
let finalObject = {};
const keys = Object.keys(data);
for (const key of keys) {
// If key is Array [], recursively add each element in Array
if (data[key] instanceof Array) {
finalObject[key] = [];
for (let i = 0; i < data[key].length; i++) {
const res = transform(data[key][i], targetType[key][i]);
finalObject[key].push(res);
}
}
// If key is Object {}, recursively add Object keys
else if (data[key] instanceof Object) {
finalObject[key] = transform(data[key], targetType[key]);
}
// If key is Primitive, we can directly add key
else {
switch (typeof targetType[key]) {
case 'string':
finalObject[key] = data[key].toString();
break;
case 'boolean':
finalObject[key] = data[key] ? 'Yes' : 'No';
break;
case 'number':
finalObject[key] = Number(data[key]);
break;
}
}
}
return finalObject;
};
const data = {
a: "15",
b: "foo",
c: false,
d: {
da: 99,
db: [{
dba: "1.2",
dbb: true
}]
}
}
const targetType = {
a: 27,
b: "foofoo",
c: true,
d: {
da: "bar",
db: [{
dba: 4,
dbb: false
}]
}
}
const finalObject = transform(data, targetType);
console.info('Final Object : ', finalObject);Благодарю вас! Сам бы я не догадался. Что касается варианта использования, последний объект используется для создания отчета Excel с xlsx-шаблон. Мы не полностью контролируем входные данные, поэтому нам нужно убедиться, что типы правильные (например, от 11 до 11). Я переключаю тег на JS, чтобы другим людям с похожей проблемой было легче найти.
Вы можете написать пример A, B и C?