ale917k
ale917k

Reputation: 1768

No index signature with a parameter of type 'string' was found on type DataType

I have a basic React app which simply filters an object removing its empty fields.

import "./styles.css";

type DataType = {
  data1: string;
  data2: string;
};

const App: React.FC = () => {
  const [data, setData] = useState<DataType>({
    data1: "",
    data2: ""
  });

  // Create temp obj and remove empty fields
  const removeEmptyFields = () => {
    const filteredData = data;
    Object.keys(filteredData).forEach(
      (key) => filteredData[key] === "" && delete filteredData[key]
    );
    setData(filteredData);
  };

  const addEmptyFields = () => {
    setData({
      data1: "",
      data2: ""
    });
  };

  console.log(data);

  return (
    <div className="App">
      <button onClick={addEmptyFields}>Add empty fields</button>
      <button onClick={removeEmptyFields}>Remove empty fields</button>
    </div>
  );
};

export default App;

What I'm trying to achieve, is to convert the function to Typescript, but am encountering the following error on filteredData[key]:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'DataType'.
No index signature with a parameter of type 'string' was found on type 'DataType'.ts(7053)

I've tried many solutions, some of which can be found here, but none of them helped with the error.

I've actually encountered this issue on multiple places where I need to get an object at position 'key' (obj[key]), but am not understanding what is Typescript actually missing in this type of situation?

A working playground can be found here

Any suggestion is highly appreciated, so thank you a lot in advance!

Upvotes: 1

Views: 1076

Answers (2)

ggirodda
ggirodda

Reputation: 780

it is always better to avoid modifying the original object

type DataType = { [key: string]: string }

const [data, setData] = useState<DataType>({
  data1: '',
  data2: '',
})

const removeEmptyFields = () => {
  const filteredData = Object.entries(data).reduce(
    (acc, [key, value]) => ({ ...acc, ...(value !== '' && { [key]: value }) }),
    {}
  )
  setData(filteredData)
}

Upvotes: 3

Ramesh Reddy
Ramesh Reddy

Reputation: 10662

You can use type assertion:

const removeEmptyFields = () => {
    const filteredData = data;
    (Object.keys(filteredData) as (keyof DataType)[]).forEach(
      (key) => filteredData[key] === "" && delete filteredData[key]
    );
    setData(filteredData);
  };

Upvotes: 1

Related Questions