A generic React component keeps related prop types in sync without fixing their content type in advance. A paginated list, for example, can accept both employee records and high-score entries while requiring its renderer to accept the same item type as the list. section 5.3 section 6.2
Type a reusable paginator
```tsx interface PaginableItemProps<Type> { item: Type; index: number; } interface PaginableProps<Type> { items: Type[]; Renderer: FC<PaginableItemProps<Type>>; className?: string; } export function Paginable<Type>({ items, Renderer, className }: PaginableProps<Type>) { // Select the current page, then render its items. } ``` The single `Type` parameter links `items` to `Renderer`: an employee renderer belongs with employee items, while a high-score renderer belongs with high-score entries. In the complete paginator, `useState` tracks the current page, `slice` selects four items, and page controls allow each mounted list to navigate independently. section 6.2
Wrapping a generic component can disrupt that relationship. With `forwardRef`, the item type can become `unknown`, so a renderer expecting an employee no longer matches. `memo` presents the same type-preservation problem; do not assume either wrapper retains the original generic signature. section 6.2.1 section 6.2.2
Choose a repair according to how often the pattern occurs:
- For an occasional forwarded ref, cast the wrapped component to a generic signature that includes `RefAttributes` for the referenced element. The signature is cumbersome, so explain the cast to maintainers. section 6.2.1
- For `memo`, cast the result to `typeof` the original component; memoization does not otherwise change its type signature. section 6.2.2
- For many such components, augment React’s `forwardRef` or `memo` type declarations in a `.d.ts` file instead of repeating casts. This changes typings across the application, so use it deliberately. section 6.2.1 section 6.2.2
function PaginableWithoutRef<Type>( #1
{ items, Renderer, className }: PaginableProps<Type>,
ref: Ref<HTMLElement>
) {
...
}
const Paginable =
forwardRef(PaginableWithoutRef) as <Type>( #2
p: PaginableProps<Type> #2
& RefAttributes<HTMLElement> #2
) => ReturnType<typeof PaginableWithoutRef>; #2
The forwarded-ref listing shows the explicit generic cast, including `RefAttributes<HTMLElement>`, that restores the relationship between item and renderer types. section 6.2.1
