Reputation: 1768
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
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
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