Элемент TS 7023 неявно имеет тип «любой», поскольку выражение типа «любой» не может использоваться для индексации типа «{}»

Я получаю параметры поля выбора, перебираю метки, группу опций и значения в поле выбора. Что-то не так с тем, как я создал свои типы?

interface Option {
  label: string
  value: string
  selected?:boolean
  mainGroup?: string
  optgroup?: "" | string | [] | undefined
}

const trackNames: Option[] = [
  {
    value: "Track1",
    label: "Track One",
    optgroup: "",
  },
  {
    value: "Track2",
    label: "Track Two",
    optgroup: "",
  },
  {
    value: "Track3",
    label: "Track Three",
    optgroup: "Track3-Group",
  },
  {
    value: "Track4",
    label: "Track Four",
    optgroup: "Track3-Group",
  }
];

// код sample.js

import { trackNames as trackNameData } from '/helper/Data'

const groupedOptions = {};
  
trackNameData.forEach((option: { optgroup: any; value: any; label: any }) => {
    
  if (!groupedOptions[option.optgroup]) groupedOptions[option.optgroup] = [];
    groupedOptions[option.optgroup].push({
      value: option.value,
      label: option.label,
  });

});

const renderOptions = (options: any[]) => {
   return options.map((option) => {
     return (
       <option key = {option.value} value = {option.value}>
         {option.label}
       </option>
       );
    });
};

<select>   
    <option value=''>Please select</option>
    {Object.keys(groupedOptions).map((group, index) => {
    return (
      <optgroup key = {index} label = {group}>
      {renderOptions(groupedOptions[group])}
    </optgroup>
    );
    })}
</select>

Когда я импортирую trackData в другой файл JS для отображения параметров в поле выбора, я получил ошибку ниже:

Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{}'.ts(7053)

Что я делаю не так? Я рассмотрел другие решения и не могу заставить их работать.

🤔 А знаете ли вы, что...
JavaScript поддерживает работу с различными форматами данных, такими как JSON и XML.


1
79
2

Ответы:

Решено

Если вы собираетесь индексировать groupedOptions с каким-то произвольным ключом, то вам нужно присвоить ему тип с сигнатурой индекса . Из вашего примера кода я ожидаю, что вы хотите, чтобы значения были массивами Options. Таким образом, тип {[k: string]: Option[]} или его эквивалент Record<string, Option[]> (с использованием типа утилиты Record) будет работать:

const groupedOptions: Record<string, Option[]> = {};

Как только вы это сделаете, запись groupedOptions[xxx] не будет ошибкой, если xxx похож на ключ:

trackNames.forEach((option: { optgroup?: any; value: any; label: any }) => {
  if (!groupedOptions[option.optgroup]) groupedOptions[option.optgroup] = [];
  groupedOptions[option.optgroup].push({
    value: option.value,
    label: option.label,
  });
});

Теперь это компилируется так, как написано, без ошибок. Но обратите внимание, что вы указали optgroupнамеренно потерять любой тип , что в большинстве случаев отключает проверку типов. Вообще говоря, вам следует индексировать только объекты с string, number или symbol. Если optgroup действительно может быть undefined или пустым массивом [] (обратите внимание, что [] — это тип кортежа с нулевыми элементами, а не произвольный тип массива), то индексация объекта с его помощью будет иметь неожиданные результаты. Я считаю, что это выходит за рамки заданного вопроса, но вам действительно следует убедиться, что ключи вашего объекта действительны.

Детская площадка, ссылка на код


interface Option {
  label: string
  value: string
  selected?:boolean
  mainGroup?: string
  optgroup?: "" | string | [] | undefined
}

const trackNames = [
  {
    value: "Track1",
    label: "Track One",
    optgroup: "",
  },
  {
    value: "Track2",
    label: "Track Two",
    optgroup: "",
  },
  {
    value: "Track3",
    label: "Track Three",
    optgroup: "Track3-Group",
  },
  {
    value: "Track4",
    label: "Track Four",
    optgroup: "Track3-Group",
  }
] as const satisfies Option[];
const groupedOptions: { [key in typeof trackNames[number]['optgroup']]: { value: string, label: string }[] } = {} as any;
  
trackNames.forEach((option) => {
  if (!groupedOptions[option.optgroup]) groupedOptions[option.optgroup] = [];
  groupedOptions[option.optgroup].push({
    value: option.value,
    label: option.label,
  });
});