I am trying to convert a function from Javascript to Typescript but I keep running into the following error:
Type 'undefined' cannot be used as an index type
I understand that undefined cannot be used as an index, but I have tried the null check for the index type as well as conditional rendering but nothing seems to work.
Here is my code:
useState hook of values I am using for the function
const [newUser, setNewUser] = useState({
firstName: "",
lastName: "",
companyName: "",
email: "",
password: "",
id: ""
});
const [errorMessage, setErrorMessage] = useState("");
function which is essentially taking the newUser initial values, making a copy of that object, then calling setNewUser to populate the fields entered by the user into a newUser copied object.
const setValues = (propName?: number, value?: any) => {
const cloneUser = { ...newUser };
cloneUser[propName] = value;
setNewUser({ ... cloneUser });
setErrorMessage("");
}
My main issue is the cloneUser[propName]
cannot be undefined and used as an index and I'm not sure how to get around this.
CodePudding user response:
Answer
Redefine the setValues
function as:
const setValue = (propName: keyof typeof newUser, value: string) => {
// your update code here
}
The parameter types are changed to match your state type, which is inferred as:
{
firstName: string;
lastName: string;
companyName: string;
email: string;
password: string;
id: string;
}
Alternatively
Specify the type for state:
type User = Readonly<{
firstName: string;
lastName: string;
companyName: string;
email: string;
password: string;
id: string;
}>;
// in the component
const [newUser, setNewUser] = useState<User>({
// initialize here
});
and define the function as:
const setValue = (propName: keyof User, value: string) => { ... }
Explanation
The propName
cannot be a number | undefined
, since it is used to index an object with string
keys (your state). It has to be a string
.
The problem that you are facing is caused by the propName
parameter defined as propName?: number
.
This (propName?: number, value?: any) => { ... }
is equivalent to (propName: number | undefined, value: any | undefined) => { ... }
. This means that in your setValues
function, propName
could be undefined, which is correctly detected as an error, because undefined
value cannot be used to index an object.
Suggestions
I would also suggest to change the name of the function to setValue
, as you are only setting one given property at the time.
Additionally, you are setting string values, so the value can also be non-optional and typed as string
.
CodePudding user response:
Looks like you're trying to arbitrarily add a key value pair to this object with a numeric key and any value. You need to tell typescript that this is allowed by defining a type, and passing it to the generic parameter of useState
.
demo: https://stackblitz.com/edit/react-ts-mpdukw?file=App.tsx
type User = {
firstName: string;
lastName: string;
companyName: string;
email: string;
password: string;
id: string;
[key: number]: any; // This lets you add a numeric key with any value
};
// generic parameter defines the type of `newUser`
const [newUser, setNewUser] = useState<User>({
firstName: '',
lastName: '',
companyName: '',
email: '',
password: '',
id: '',
});
Then, it doesn't make sense to allow an undefined key, so make that property mandatory:
const setValues = (propName: number, value?: any) => {
setNewUser({ ...newUser, [propName]: value });
setErrorMessage('');
};
Depending on the use case, you may want to allow an undefined key and just skip steps in that case.
const setValues = (propName?: number, value?: any) => {
if (propName) setNewUser({ ...newUser, [propName]: value });
setErrorMessage('');
};