1

Here I have a component that should print a toast adding an icon to the content depending on the type of the toast:

import * as React from 'react';
import { toast }  from 'react-toastify';
import { FaInfo, FaCheck, FaExclamationTriangle, FaBug, FaExclamationCircle } from 'react-icons/fa';
import { TypeOptions, ToastContent, Toast } from 'react-toastify/dist/types/index';

interface IToast {
  message: ToastContent;
  type: TypeOptions;
}
    
const displayIcon = ({ type }: IToast) => {
          switch (type) {
            case 'success':
              return <FaCheck />;
            case 'info':
              return <FaInfo />;
            case 'error':
              return <FaExclamationCircle />;
            case 'warning':
              return <FaExclamationTriangle />;
            default:
              return <FaBug />;
          }
        };
    
const myToast = ({ type, message }: IToast): Toast => {
  return toast[type](
    <div>
      <div>
        {displayIcon(type)}
      </div>
      <div>{message}</div>
    </div>,
  );
};

export default myToast;

Im rendering myToast on another component by doing:

const notify = React.useCallback((message: ToastContent, type: ToastOptions) => {
lomplayToast({ message, type });
  }, []);

The components already work and they do what they are intended to. But Im not able to make a good type declaration. The Toast interface comes with several interface and type declarations. One of them is ToastOptions type which the displayIcon is able to retrieve. My questions:

  1. Why does the toast[type] attribute throws "Property 'default' does not exist on type '{ (message: ToastContent, type: TypeOptions | undefined): ReactText;..."? Where is this default property coming from?

1 Answers1

0

There are 2 places where types could be declared on a function.

  1. You can declare types for the props.
  2. You can declare a type for what the function returns, a ReturnType.

it looks like this

const yourFunction = (props: PropType): ReturnType => { ... }

You declared your ToastProps as a ReturnType.

Do this:

const myToast = ({ type, message }: ToastProps) => { ... }

instead of:

const myToast = ({ type, message }): ToastProps => { ... }

It's a very subtle change.


Note: This counts for any function, but React has their own types for functions. You can type a React component function like this:

const myToast: React.FunctionComponent<ToastProps> = ({ message, type }) => { ... }

Behind the scenes, it will create something like this:

const myToast = (props: ToastProps): JSX.Element => { ... }
// It does some more stuff, but I simplified it for this example.
Luïs
  • 2,671
  • 1
  • 20
  • 33
  • Thank you so much! Then how would you edit the callback function from the outer component to set the values of the const myToast? Ive changed the type as suggested and it does infer the types correctly but the outer component says `An argument matching this binding pattern was not provided.` – Nicolás Guasca Santamaría Apr 26 '21 at 19:29
  • Ah I see, your `myToast` function is not actually a React Component. It is being used as a callback, not as a component. My bad, I misread your code. You can ignore the last part of my answer. Just declaring your `myToast` function like this: `const myToast = ({ type, message }: ToastProps) => { ... }` should do the trick. – Luïs Apr 26 '21 at 19:37