petyosi / react-virtuoso

The most powerful virtual list component for React
https://virtuoso.dev
MIT License
5.06k stars 299 forks source link

[BUG] Breaking change from @types/react@18.2.61 #1045

Closed Xavier59 closed 4 months ago

Xavier59 commented 4 months ago

Describe the bug https://github.com/DefinitelyTyped/DefinitelyTyped/pull/68720 has caused a breaking change.

Reproduction

const components: TableComponents<DataType, Context> = {
    Scroller: forwardRef<HTMLDivElement>((props, ref) => <MUITableContainer {...props} ref={ref} />),
    TableRow: ({ item, ...props }: { item: DataType }) => <StyledRow {...props} />,
    Table: props => <Table {...props} style={{ borderCollapse: 'separate', overflowAnchor: 'none' }} />,
    TableHead,
    EmptyPlaceholder: ({ context }: { context?: Context }) => (
        <TableBody>
            <NoDataRow>{emptyState?.(context)}</NoDataRow>
        </TableBody>
    ),
    TableBody: forwardRef<HTMLTableSectionElement>((props, ref) => <TableBody {...props} ref={ref} />),
};

Scroller and TableBody are not the right type.

Type 'ForwardRefExoticComponent<RefAttributes<HTMLDivElement>>' is not assignable to type 'ComponentType<Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "style" | ... 1 more ... | "children"> & { ...; } & { ...; }> | undefined'.
  Type 'ForwardRefExoticComponent<RefAttributes<HTMLDivElement>>' is not assignable to type 'FunctionComponent<Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "style" | ... 1 more ... | "children"> & { ...; } & { ...; }>'.
    Types of property 'propTypes' are incompatible.
      Type 'WeakValidationMap<RefAttributes<HTMLDivElement>> | undefined' is not assignable to type 'WeakValidationMap<Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "style" | ... 1 more ... | "children"> & { ...; } & { ...; }> | undefined'.
        Type 'WeakValidationMap<RefAttributes<HTMLDivElement>>' is not assignable to type 'WeakValidationMap<Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "style" | ... 1 more ... | "children"> & { ...; } & { ...; }>'.
          Types of property 'ref' are incompatible.
            Type 'Validator<LegacyRef<HTMLDivElement> | undefined> | undefined' is not assignable to type 'Validator<string | Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "ref">> | undefined'.
              Type 'Validator<LegacyRef<HTMLDivElement> | undefined>' is not assignable to type 'Validator<string | Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "ref">>'.
                Type 'LegacyRef<HTMLDivElement> | undefined' is not assignable to type 'string | Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "ref">'.
                  Type 'undefined' is not assignable to type 'string | Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "ref">'.ts(2322)
index.d.ts(492, 5): The expected type comes from property 'Scroller' which is declared here on type 'TableComponents<DataType, Context>'

Expected behavior No typescript error

mrlika commented 4 months ago

A similar issue with @types/react@18.2.61

This component is not assignable to components.List any more:

const EmployeesList = forwardRef<HTMLDivElement, ListProps>(({ children, ...restProps }, ref) => (
  <div className='employees-list' {...restProps} ref={ref}>
    {children}
  </div>
));

<Virtuoso
  className='grid-table-body scrollbar-light-theme'
  data={sortedEmployeesList}
  components={{ List: EmployeesList }}
  overscan={500}
  itemContent={(_, employee) => renderEmployeeRow(employee)}
/>

With the TypeScript error:

Type 'ForwardRefExoticComponent<Omit<ListProps, "ref"> & RefAttributes<HTMLDivElement>>' is not assignable to type 'ComponentType<Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "ref" | ... 1 more ... | "children"> & { ...; } & { ...; }> | undefined'.
  Type 'ForwardRefExoticComponent<Omit<ListProps, "ref"> & RefAttributes<HTMLDivElement>>' is not assignable to type 'FunctionComponent<Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "ref" | ... 1 more ... | "children"> & { ...; } & { ...; }>'.
    Types of property 'propTypes' are incompatible.
      Type 'WeakValidationMap<Omit<ListProps, "ref"> & RefAttributes<HTMLDivElement>> | undefined' is not assignable to type 'WeakValidationMap<Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "ref" | ... 1 more ... | "children"> & { ...; } & { ...; }> | undefined'.
        Type 'WeakValidationMap<Omit<ListProps, "ref"> & RefAttributes<HTMLDivElement>>' is not assignable to type 'WeakValidationMap<Pick<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ...; }, "ref" | ... 1 more ... | "children"> & { ...; } & { ...; }>'.
          Types of property 'ref' are incompatible.
            Type 'Validator<LegacyRef<HTMLDivElement> | undefined> | undefined' is not assignable to type 'Validator<((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null | undefined> | undefined'.
              Type 'Validator<LegacyRef<HTMLDivElement> | undefined>' is not assignable to type 'Validator<((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null | undefined>'.
                Type 'LegacyRef<HTMLDivElement> | undefined' is not assignable to type '((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null | undefined'.
                  Type 'string' is not assignable to type '((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null | undefined'.ts(2322)
petyosi commented 4 months ago

I'll have to check what the author did as a migration. @mrlika @Xavier59 - happy to accept a PR if you have the capacity, should be a small change I hope.

github-actions[bot] commented 4 months ago

:tada: This issue has been resolved in version 4.7.2 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

fdw commented 4 months ago

I still see a similar error with react-virtuoso: 4.7.2 and @types/react: 18.2.65:

const VirtuosoTableComponents: WithRequired<TableComponents, 'Scroller' | 'TableBody'> = {
  TableFoot: TableFooter,
  Scroller: forwardRef((props, ref) => <TableContainer component={Paper} {...props} ref={ref} />),
  Table: Table,
  TableHead: TableHead,
  TableRow: TableRow,
  TableBody: forwardRef((props, ref) => <TableBody {...props} ref={ref} />)
}

with export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }

src/components/common/table/VirtuosoTableComponents.tsx:14:3 - error TS2322: Type 'OverridableComponent<TableFooterTypeMap<{}, "tfoot">>' is not assignable to type 'ComponentType<Pick<DetailedHTMLProps<HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, "style" | "children"> & { ...; } & RefAttributes<...>> | undefined'.
  Type 'OverridableComponent<TableFooterTypeMap<{}, "tfoot">>' is not assignable to type 'FunctionComponent<Pick<DetailedHTMLProps<HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, "style" | "children"> & { ...; } & RefAttributes<...>>'.
    Types of parameters 'props' and 'props' are incompatible.
      Type 'Pick<DetailedHTMLProps<HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, "style" | "children"> & { ...; } & RefAttributes<...>' is not assignable to type '{ component: any; } & TableFooterOwnProps & CommonProps & Omit<any, "className" | "style" | "classes" | "children" | "sx">'.
        Property 'component' is missing in type 'Pick<DetailedHTMLProps<HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, "style" | "children"> & { ...; } & RefAttributes<...>' but required in type '{ component: any; }'.

14   TableFoot: TableFooter,
     ~~~~~~~~~

  node_modules/@mui/material/OverridableComponent.d.ts:21:7
    21       component: RootComponent;
             ~~~~~~~~~
    'component' is declared here.
  node_modules/react-virtuoso/dist/index.d.ts:478:5
    478     TableFoot?: React_2.ComponentType<Pick<React_2.ComponentProps<'tfoot'>, 'style' | 'children'> & {
            ~~~~~~~~~
    The expected type comes from property 'TableFoot' which is declared here on type 'WithRequired<TableComponents<unknown, unknown>, "Scroller" | "TableBody">'

Am I doing something wrong?

chitoku-k commented 4 months ago

@fdw You can circumvent that with this way:

import type { ComponentPropsWithoutRef } from 'react'
import { forwardRef } from 'react'
import type { TableComponents } from 'react-virtuoso'
import Paper from '@mui/material/Paper'
import Table from '@mui/material/Table'
import TableBody from '@mui/material/TableBody'
import TableContainer from '@mui/material/TableContainer'
import TableFooter from '@mui/material/TableFooter'
import TableHead from '@mui/material/TableHead'
import TableRow from '@mui/material/TableRow'

const VirtuosoTableComponents: TableComponents = {
  TableFoot: forwardRef((props: ComponentPropsWithoutRef<'tfoot'>, ref) => (
    <TableFooter ref={ref} {...props} />
  )),
  Scroller: forwardRef((props: ComponentPropsWithoutRef<'div'>, ref) => (
    <TableContainer ref={ref} component={Paper} {...props} />
  )),
  Table,
  TableHead: forwardRef((props: ComponentPropsWithoutRef<'thead'>, ref) => (
    <TableHead ref={ref} {...props} />
  )),
  TableRow,
  TableBody: forwardRef((props: ComponentPropsWithoutRef<'tbody'>, ref) => (
    <TableBody ref={ref} {...props} />
  )),
}
fdw commented 4 months ago

That was quick! Thank you! 🙂

Sweater-Baron commented 3 weeks ago

@fdw You can circumvent that with this way:...

This worked for me, but I had to do forwardRef<HTMLTableSectionElement>, or otherwise it complained about the ref being unknown type.