Trying to add typescript to custom React Form Component and can't rid of mistake i don't know how to fix. TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ username: string; email: string; password: string; confirmPassword: string; }'. No index signature with a parameter of type 'string' was found on type '{ username: string; email: string; password: string; confirmPassword: string; }'.
I'm sure there is an answer somewhere, but i can't adjust it to my code as well as can't understand the basic of mistake. Please help me understand
App Component
import React, {useState} from 'react';
import s from './App.module.scss'
import Input from "./components/Input/Input";
function App() {
const [values, setValues] = useState({
username: '',
email: '',
password: '',
confirmPassword: '',
});
const inputs = [
{
id: "username",
name: "UserName",
type: "text",
placeholder: "Username",
},
{
id: "email",
name: "Email",
type: "text",
placeholder: "@gmail.com",
},
]
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValues({...values, [e.target.name]: e.target.value});
}
return (
<div className={s.app}>
<form action="">
{inputs.map((input) => (
<Input
key={input.id}
id={input.id}
name={input.name}
placeholder={input.placeholder}
type={input.type}
value={values[input.name]}
onChange={handleChange}
/>
))}
</form>
</div>
);
}
export default App;
Input Component
import React, {FC} from 'react';
import s from './Input.module.scss';
interface InputProps {
id: string,
name: string,
placeholder: string,
type: string,
value: string,
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void,
}
const Input: FC<InputProps> = ({id, name, placeholder, type, value, onChange}) => {
return (
<div className={s.input}>
<label htmlFor={id}>
{name}
</label>
<input
id={id}
type={type}
placeholder={placeholder}
value={value}
onChange={onChange}
/>
</div>
);
};
export default Input;
Source code: https://github.com/Endo-Resu/react-custom-form
Thank you for ur time, advices and help
Solution:
App component
import React, { useState } from "react";
import s from "./App.module.scss";
import Input from "./components/Input/Input";
function App() {
const [values, setValues] = useState({
username: "",
email: "",
password: "",
confirmPassword: ""
});
const inputs: {
id: string;
name: keyof typeof values;
type: string;
placeholder: string;
}[] = [
{
id: "username",
name: "username",
type: "text",
placeholder: "Username"
},
{
id: "email",
name: "email",
type: "text",
placeholder: "@gmail.com"
}
];
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValues({ ...values, [e.target.name]: e.target.value });
};
return (
<div className={s.app}>
<form action="">
{inputs.map((input) => (
<Input
key={input.id}
id={input.id}
name={input.name}
placeholder={input.placeholder}
type={input.type}
value={values[input.name]}
onChange={handleChange}
/>
))}
</form>
</div>
);
}
export default App;
Explanation:
As the previous answer explained, the error is in this line value={values[input.name]}
and the reason for the error is that the object values
cannot be indexed by any random string, the index has to be one of values
declared properties (like username
).
The solution is to give inputs.name
a type that can be used as index of values
:
const inputs: {
id: string;
name: keyof typeof values;
type: string;
placeholder: string;
}[] = ...
Now the property name
has a type of whatever keys in values
. Now input.name
can be used to index values
.