Search code examples
reactjstypescriptreact-context

Typescript react context + Type '{}' has no call signatures


I have created a Notification Toast service which seems to be working except for some typescript errors surrounding the ToastContext.

Calling the toast on any page I import my useToast() hook which connects to the contextProvider. The typescript error occurs with the toast(...) function. The error I receive is

Error This expression is not callable. Type '{}' has no call signatures.

Toast Hook

<button
    onClick={() => {
        return toast({
            title: "I am toasty"
        });
    }}
>Toast Me</button>

Context & useContext hook

export const ToastContext = createContext({});

export function useToast() {
  return useContext(ToastContext);
}

Here is a codesandbox to the current code https://codesandbox.io/s/dazzling-spence-clehl.

I have tried typing my createContext with

interface ContextType {
   toasts: []
   toast: () => void
}

export const ToastContext = createContext<ContextType | {}>({});

Solution

  • Your context value is a function, while you initialize the context with an empty object (why?), so on static type evaluation, calling toast() is a try to emit a function on an object ('{}' has no call signatures).

    Fix your initialization according to its usage:

    // toast is a function
    <ToastContext.Provider value={toast}>{children}</ToastContext.Provider>
    
    export const ToastContext = createContext((payload: any) => {});
    

    Or, I guess your initial idea was trying to do something like:

    // import ToastProps
    interface ContextType {
      toasts: [] | ToastProps[];
      toast: (payload: any) => void;
    }
    
    export const ToastContext = createContext<ContextType>({
      toast: () => {},
      toasts: []
    });
    
    // Initilization
    const { toast, toasts } = useToasts();
    
    // Pass ContextType
    <ToastContext.Provider value={{toast, toasts}}>{children}</ToastContext.Provider>
    
    // Context usage
    const { toast } = useToast();
    toast(); // is a function, GOOD
    

    Where ContextType matches useToast return value and createContext (Try reuse ContextType with useToast return value).

    Edit Context Types Fix