Álvaro
Álvaro

Reputation: 2598

How to declare types on Typescript for spread props

I am trying to figure out how to get this code to work on TypeScript

type ScrollProps = {
  autoHide: boolean
  autoHideTimeout: number
  autoHideDuration: number
}

const renderThumb = ({ style, ...props}) => {
  const thumbStyle = {
    borderRadius: 6,
    backgroundColor: 'rgba(35, 49, 86, 0.8)'
  }
  return <div style={{ ...style, ...thumbStyle }} {...props} />
}

const CustomScrollbars = (props: ScrollProps) => (
  <Scrollbars
    renderThumbHorizontal={renderThumb}
    renderThumbVertical={renderThumb}
    {...props}
  />
)

...
<CustomScrollbars autoHide autoHideTimeout={500} autoHideDuration={200}>
 ...
</CustomScrollbars>

If I create a type for the props on CustomScrollbars I get an error on <CustomScrollbars>, if I don't I get an error on the props at the CustomScrollbars function.

I also get an error on style, it wants to know what type, but I do not know what type to put.

Why does the implicit any not work and how can I make this code to work on TypeScript?

https://codesandbox.io/s/react-hooks-with-typescript-forked-8g5g6

Upvotes: 3

Views: 1672

Answers (2)

Linda Paiste
Linda Paiste

Reputation: 42298

In all honestly the types for the react-custom-scrollbars package are really lacking. The expected type for the renderThumbHorizontal and renderThumbVertical props is declared as React.StatelessComponent<any> -- a component that takes any props. So I have no idea if the props that those components will be called with match the props that your renderThumb is expecting.

As far as declaring the props for renderThumb (which I recommend capitalizing, as is will create problems if you try to use it in JSX like <renderThumb />), the spread operator doesn't really matter. You are accepting an object of props and all of them are passed down to a div. So we want to accept whatever props a div would accept. That type is JSX.IntrinsicElements['div'].

With this definition, style is type React.CSSProperties | undefined. It's actually ok to spread undefined, so you don't need to require style or set a default.

const RenderThumb = ({ style, ...props}: JSX.IntrinsicElements['div']) => {
  const thumbStyle = {
    borderRadius: 6,
    backgroundColor: 'rgba(35, 49, 86, 0.8)'
  }
  return <div style={{ ...style, ...thumbStyle }} {...props} />
}

As far as the CustomScrollbars, you can import the props from the package rather than having to redefine them yourself. If you type the component as React.FunctionComponent<Props> that will include the children prop automatically. (But something is wonky with your CodeSandbox because it can't find that type).

import React from "react";
import { Scrollbars, ScrollbarProps } from "react-custom-scrollbars";

const CustomScrollbars: React.FC<ScrollbarProps> = (props) => (
  <Scrollbars
    renderThumbHorizontal={renderThumb}
    renderThumbVertical={renderThumb}
    {...props}
  />
);

Upvotes: 2

First Arachne
First Arachne

Reputation: 829

I think you need to add children into the props type.

And for style, add the following type

const renderThumb = ({ style, ...props}: {style: React.CSSProperties}) => {
}

Upvotes: 1

Related Questions