Typescript Parameter Object Destructuring

68 Views Asked by At

I am getting a Typescript error for props.className below:

type PropsType = {
  handleChange?: Function;
  props?: { [key: string]: any };
};

export default function Search({ handleChange, ...props }: PropsType) {
  return (
    <div className={`search-bar flex middle ${props.className ?? ""}`}>
      <div className="search-icon flex middle">
        <svg>
          <use href="#search-icon" />
        </svg>
      </div>
      <input placeholder="Search" size={1} />
    </div>
  );
}

I get the error "Property 'className' does not exist on type '{ props?: { [key: string]: any; } | undefined; }'" but that's to be expected since I'm spreading the rest of the parameters in, right? I just want to add the className to the element if it's there (in props).

For additional info, I'm converting this Component to Typescript and am using Next.js 13 (experimental).

2

There are 2 best solutions below

1
Jerryh001 On BEST ANSWER

To pass any props to a component, the string signature should be defined as the following:

type PropsType = {
    handleChange?: Function;
    [key: string]: any
};

This makes you code work but not suggest because it disable all type checks.


And in my opinion, className is a known property so it should be explicitly defined:

type PropsType = {
    handleChange?: Function;
    className?: string;
};
1
Nils Kähler On

To utilize the full potential of Typescript and brings a static type system to Javascript you should create a props type with the elements written out. this will tell typescript what types you expect to be passed to the component. Otherwise you lose out on some of the benefits that typescript brings, since defining [key: string]: any essentially removes the static types, since you can now input everything.

type PropsType = {
  handleChange?: Function;
  propsClassName: string;
};

function Search({ handleChange, propsClassName }: PropsType) {
  return (
    <div className={`search-bar flex middle ${propsClassName ?? ""}`}>
      <div className="search-icon flex middle">
        <svg>
          <use href="#search-icon" />
        </svg>
      </div>
      <input placeholder="Search" size={1} />
    </div>
  );
}