Borislav Hadzhiev
Wed Apr 20 2022·2 min read
Photo by Soroush Karimi
To type the useState
hook with an empty object initial value in React, use
the hook's generic, e.g.
const [employee, setEmployee] = useState<{[key: string]: any}>({})
. The state
variable will be typed as an object with dynamic properties and values.
import {useEffect, useState} from 'react'; const App = () => { // 👇️ const employee: {[key: string]: any;} const [employee, setEmployee] = useState<{[key: string]: any}>({}); useEffect(() => { setEmployee({ name: 'Alice', salary: 100, department: 'Dev', tasks: ['dev', 'test', 'ship'], }); }, []); return ( <div> <h2>Name: {employee.name}</h2> <h2>Salary: {employee.salary}</h2> </div> ); }; export default App;
The {[key: string]: any}
syntax is an
index signature
in TypeScript and is used when we don't know all the names of a type's
properties and the shape of the values ahead of time.
string
, it will return a value of any
type.You can use this approach when you don't know all of the object's properties in advance.
You might try to override the type of a specific property with an index signature.
import {useEffect, useState} from 'react'; type Employee = { [key: string]: any; age?: number; tasks?: string[]; }; const App = () => { // 👇️ const employee: {[key: string]: any;} const [employee, setEmployee] = useState<Employee>({}); useEffect(() => { setEmployee({ name: 'Alice', salary: 100, department: 'Dev', tasks: ['dev', 'test', 'ship'], }); }, []); return ( <div> <h2>Name: {employee.name}</h2> <h2>Salary: {employee.salary}</h2> </div> ); }; export default App;
We marked the age
and tasks
properties as
optional
and specified exact types for them.
Optional properties can either have an undefined
value or be of the specified
type.
This is why we are still able to initialize the state object as empty.
age
and tasks
properties can only be set to the specified type.If some of the properties of the object can be of multiple types, use a union.
import {useEffect, useState} from 'react'; type Employee = { [key: string]: any; // 👇️ age is number OR string age?: number | string; tasks?: string[] | number[]; }; const App = () => { // 👇️ const employee: {[key: string]: any;} const [employee, setEmployee] = useState<Employee>({}); useEffect(() => { setEmployee({ name: 'Alice', salary: 100, department: 'Dev', tasks: ['dev', 'test', 'ship'], }); }, []); return ( <div> <h2>Name: {employee.name}</h2> <h2>Salary: {employee.salary}</h2> </div> ); }; export default App;
We used a
union
to set the age
property to be of type number
or string
.
You can repeat this process to include as many types as necessary.