6

I am trying to type the following two parameters passed to Row function.

//https://github.com/bvaughn/react-window

import * as React from "react";
import styled from "styled-components";
import { FixedSizeList as List } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";

const StyledSection = styled.section`
  width: 100vw;
  height: 100vh;
  background: #C0C0C0;
`;

const Row = ({ index, style }) => (
  <div className={index % 2 ? 'ListItemOdd' : 'ListItemEven'} style={style}>
    Row {index}
  </div>
);

const Scroller = () => {
  return (
    <StyledSection>
      <AutoSizer>
        {({ height, width }) => {
          return (
            <List height={height} width={width} itemSize={20} itemCount={300}>
              {Row}
            </List>
          );
        }}
      </AutoSizer>
    </StyledSection>
  );
};

export { Scroller };

So the following snippet of code typescript infers the index and style parameters as type any. I tried to inline the type for index as number but then the compiler says index is not defined.

   const Row = ({ index, style }) => (
      <div className={index % 2 ? 'ListItemOdd' : 'ListItemEven'} style={style}>
        Row {index}
      </div>
    );

Any ideas how to provide types to these two paramaters. react-window has its own d.ts file. Here is the working codesandbox - https://codesandbox.io/s/infinite-scroller-52b7d?file=/src/Scroller.tsx

Faktor 10
  • 1,868
  • 2
  • 21
  • 29

2 Answers2

3

Is this what you seek for?

import { CSSProperties } from 'react';

const Row = ({ index, style }: { index: number; style: CSSProperties; }) => (
  <div className={index % 2 ? 'ListItemOdd' : 'ListItemEven'} style={style}>
    Row {index}
  </div>
);

You can still add typing when using object destructuring. Also you can use your IDE to find the type of style, using goto declaration on the first style of style={style}. (ctrl-b or ctrl-q in jetbrain IDE, doesn't know for VScode, sorry).

Ambroise Rabier
  • 3,636
  • 3
  • 27
  • 38
  • 1
    yes, yes, yes. Thank you. I was trying to type inside of the destructured props object, so inside the { index: number, style}. thanks again and for the CSSProperties and tooling tip. Merci! – Faktor 10 Dec 08 '20 at 13:37
  • Why add a custom type/interface when you have a well-maintained types library `@types/react-window`? Please check my answer below - https://stackoverflow.com/a/74191187/6335249. – sohammondal Oct 26 '22 at 16:41
  • 1
    @sohammondal Indeed if there is some typing available, best is to use it. In his case he was also incorrectly typing a destructured object. – Ambroise Rabier Oct 27 '22 at 10:02
3

There's a better way of adding type to the List child component as all the types are already available in the @types/react-window package. You can find them here.

For your case, it is pretty simple -

  1. First install @types/react-window as a dev dependency.
  2. Import the ListChildComponentProps type form the above-installed package.
import React from 'react'
import { ListChildComponentProps } from 'react-window'

const Row: React.FC<ListChildComponentProps> = ({ index, style }) => (
  <div className={index % 2 ? 'ListItemOdd' : 'ListItemEven'} style={style}>
    Row {index}
  </div>
);

Advanced usage

If you want the data prop to be properly typed, you can pass custom type/interface to the ListChildComponentProps.

import React from 'react'
import { ListChildComponentProps } from 'react-window'

interface Person {
  name: string
  email: string
}

const Row: React.FC<ListChildComponentProps<Person[]>> = ({ index, style, data }) => (
  <div style={style}>
    {data[index].name} - {data[index].email}
  </div>
);

sohammondal
  • 635
  • 6
  • 12