Type useState with empty Object initial value in React (TS)

avatar

Borislav Hadzhiev

Wed Apr 20 20222 min read

Type useState with empty Object initial value in React (TS) #

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.

App.tsx
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.

The index signature in the example means that when an the object is indexed with a 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.

App.tsx
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.

However, providing types for the properties that we know about in advance is useful, because the 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.

App.tsx
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.

Use the search field on my Home Page to filter through my more than 1,000 articles.