Получение ошибки при ссылке на тип в качестве индекса - PullRequest
0 голосов
/ 02 марта 2020

У меня есть массив объектов со следующей структурой

let sampleData = [
    { valueObj: { High: 4, Low: 5,  Medium: 7 } , time: "1571372233234" , sum: 16 },
    { valueObj: { High: 5, Low: 3, Medium : 1 }, time: "1571372233234" , sum: 9},
    { time: "14354545454", sum: 0},
    { time: "14354545454", sum: 0} }
];

Мне нужно взять каждый ключ внутри каждого объекта внутри массива и сформировать из него массив. В основном группировка основана на ключе, присутствующем во всех объектах. Если у объекта нет «значений», он должен возвращать 0 через val1, val2, val3.

result = [
  { name: 'High', data: [4, 5, 0, 0] }, 
  { name: 'Medium', data: [5, 3, 0, 0] }, 
  { name: 'Low', data: [7, 1, 0, 0] }
];

Здесь я передаю строку, которая будет использовать внутри limit.Я получаю эту ошибку любая не может быть использована в качестве индекса всякий раз, когда я передаю динамически строку, которая будет использоваться внутри функции Reduce при включении машинописи.

Код работает просто отлично, но после обновления до последней версии TS выдает ошибку и не компилируется

Может кто-нибудь мне помочь?

Я попробовал следующее:

const sampleData = [{ valueObj: { High: 4, Low: 5,  Medium: 7 }, time: "1571372233234", sum: 16 }, { valueObj: { High: 5, Low: 3, Medium : 1 }, time: "1571372233234", sum: 9 }, { time: "14354545454", sum: 0 }, { time: "14354545454", sum: 0 }];

const keys = ['High', 'Low', 'Medium'];

function formResult(sampleData, prop, keys){
  let grouped = sampleData.reduce((r, { [prop]: values = {} } = {}) => {
    r.forEach(({ name, data }) => data.push(values[name] || 0));       
    return r;
  }, keys.map(name => ({ name, data: [] })));
  console.log(grouped);
}

formResult(sampleData,"valueObj", keys);

Ответы [ 2 ]

1 голос
/ 02 марта 2020

Использование reduce с динамическими c ключами с Typescript может быть уродливым и, возможно, неуместно даже в Javascript при создании одного объекта. Попробуйте создать объект, в который вы помещаете данные, вне l oop - тот, чьи свойства являются именами (High, et c), а значения - числовыми массивами. Pu sh в массив чисел на каждой итерации (нажимая 0, если свойство не существует), сначала создавая свойство с массивом, если необходимо. После зацикливания превратите объект в массив объектов:

// compliant with noImplicitAny and strict options
type DataItem = {
    time: string;
    sum: number;
    valueObj?: {
        High: number;
        Medium: number;
        Low: number;
    }
};
const sampleData: DataItem[] = [
    { valueObj: { High: 4, Low: 5,  Medium: 7 } , time: "1571372233234" , sum: 16 },
    { valueObj: { High: 5, Low: 3, Medium : 1 }, time: "1571372233234" , sum: 9},
    { time: "14354545454", sum: 0},
    { time: "14354545454", sum: 0}
];
const keys = ['High', 'Low', 'Medium'] as const;
const grouped = {} as { [key: string]: number[] };
for (const item of sampleData) {
    for (const key of keys) {
        if (!grouped[key]) {
            grouped[key] = [];
        }
        grouped[key].push(item.valueObj ? item.valueObj[key] : 0);
    }
}
const output = Object.entries(grouped).map(([name, data]) => ({ name, data }));

Скомпилированный вывод:

"use strict";
const sampleData = [
    { valueObj: { High: 4, Low: 5, Medium: 7 }, time: "1571372233234", sum: 16 },
    { valueObj: { High: 5, Low: 3, Medium: 1 }, time: "1571372233234", sum: 9 },
    { time: "14354545454", sum: 0 },
    { time: "14354545454", sum: 0 }
];
const keys = ['High', 'Low', 'Medium'];
const grouped = {};
for (const item of sampleData) {
    for (const key of keys) {
        if (!grouped[key]) {
            grouped[key] = [];
        }
        grouped[key].push(item.valueObj ? item.valueObj[key] : 0);
    }
}
const output = Object.entries(grouped).map(([name, data]) => ({ name, data }));
console.log(output);

Если клавиша valueObj является динамической c, она становится намного ужаснее. Лучшее, что я мог выяснить, было, при переборе элемента массива, если у него есть собственное свойство ключа объекта, то утверждать, что элемент массива имеет тип { [possibleKeyForObj: string]: { [key: string]: number } }, что позволяет вам получить доступ к вложенному свойству:

const formResult = (
    sampleData: object[],
    possibleKeyForObj: string,
    keys: string[],
) => {
    const grouped = Object.fromEntries(keys.map(key => [key, []]));
    for (const item of sampleData) {
        for (const key of keys) {
            grouped[key].push(
                item.hasOwnProperty(possibleKeyForObj)
                    ? (item as { [possibleKeyForObj: string]: { [key: string]: number } })[possibleKeyForObj][key]
                    : 0,
            );
        }
    }
    const output = Object.entries(grouped).map(([name, data]) => ({ name, data }));
    console.log(output);
};

formResult(
    [
        { valueObj: { High: 4, Low: 5, Medium: 7 }, time: '1571372233234', sum: 16 },
        { valueObj: { High: 5, Low: 3, Medium: 1 }, time: '1571372233234', sum: 9 },
        { time: '14354545454', sum: 0 },
        { time: '14354545454', sum: 0 },
    ],
    'valueObj',
    ['High', 'Low', 'Medium'],
);
0 голосов
/ 02 марта 2020

Функция не возвращает grouped. Это может быть проблемой

const sampleData = [{
  valueObj: {
    High: 4,
    Low: 5,
    Medium: 7
  },
  time: "1571372233234",
  sum: 16
}, {
  valueObj: {
    High: 5,
    Low: 3,
    Medium: 1
  },
  time: "1571372233234",
  sum: 9
}, {
  time: "14354545454",
  sum: 0
}, {
  time: "14354545454",
  sum: 0
}];

const keys = ['High', 'Low', 'Medium'];

function formResult(sampleData, prop, keys) {
  return sampleData.reduce((r, {
    [prop]: values = {}
  } = {}) => {
    r.forEach(({
      name,
      data
    }) => data.push(values[name] || 0));
    return r;
  }, keys.map(name => ({
    name,
    data: []
  })));

}

console.log(formResult(sampleData, "valueObj", keys));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...