Search code examples
typescriptreact-hooksreact-context

Element implicitly has an 'any' type because expression of type '"employee"' can't be used to index type '{}'


we are trying to convert existing JS code into TS but stuck in updating local state data. here apiData is expected to come from API due to which we dont know possibilities of fields.

DataContext.tsx


import { createContext,useContext, useState } from "react";


interface Data {
    id: number;
    title: string;
    apiData:object;    
  }

type DataContextType = {
    myData: Data;
    updateMyData: (myData: Data) => void;
  };

  
const DataContext = createContext<DataContextType | null>(null);

export const useDataContext =()=>{ return useContext(DataContext) as DataContextType};

export const DataContextProvider =({children}: any)=>{
    const [myData, setMyData]=useState<Data>({id:1,title:'this',apiData:{}})
    const updateMyData=(myData:Data)=>{
        setMyData(myData);
    }
    
    return (
        <DataContext.Provider value={{myData,updateMyData}}>
            {children}
        </DataContext.Provider>
    )
}

page.tsx

"use client"

import { useEffect , useState} from 'react';
import {useDataContext} from '../context/DataContext' 

export default function Sample() { 
    const { myData,updateMyData } = useDataContext();
    const [name,setName]=useState([]);
    
    useEffect(()=>{
        if(name.length===0)
        {
            updateMyData({id:2,title:'that',apiData:{employee:[{data:'tom'},{data:'harry'}]}});  
            setName(myData["apiData"]["employee"]);
        }      
    },[name]);
    
  return (
    <>
     
    <h1>hellow1</h1>
    {name.map((element)=>{ return <h2>{element.data}</h2>})}     
    </>
  )
}

TS Error

enter image description here

even tough updateMyData setting up employee data we are not able to setName


Solution

  • You need to make a couple of changes to make TS play along nicely.

    apiData: object is not a well defined type. And hence you cannot use apiData["employee"]["data"], without TS screaming at you. Replace that with:

    apiData: { employee: { data: string }[] };
    

    Even with that, you will get another error:

    const [name, setName] = useState([]);
    

    The way setName is defined it can only accept an empty tuple. This happens because React-Typescript narrows the type (of state variable) to the most specific one by its own. You should define the type of the state variable while calling useState.

    Use the below to define the type:

    const [name, setName] = useState<{ data: string }[]>([]);
    

    useState is defined as a generic in typescript to facilitate using values of all types.

    Here is a demo. It is not functional but demos all the type errors and fixes.