'Infer child component generics from parent type
I would like to create a table component which utilizes components to define the columns like this:
interface UsageModel {
title: string;
}
const Usage = () => {
const data: UsageModel[] = [{ title: "Stack Overflow" }]
return <Table data={data}>
<TableField header="Title">{row => row.title}</TableField>
</Table>
}
This works technically but Typescript doesn't know the type of row (resulting in unknown) which is kinda annoying because you have to explicitly type every field.
I was expecting Typescript to get the generic type because of the typed children prop of the table but I guess this doesn't work because of how JSX is implemented?
Does anyone know of a way to teach Typescript how to do this?
EDIT: I've created a Playground with a working example here.
The table code (minus the implementation) looks like this:
import { Component, ReactElement, ReactNode } from "react"
export interface TableFieldProps<T> {
children: ((row: T) => ReactNode) | ReactNode
header?: ReactNode
}
export class TableField<T> extends Component<TableFieldProps<T>> {
}
export interface TableProps<T> {
data: T[]
children: TableFieldElement<T> | TableFieldElement<T>[]
}
type TableFieldElement<T> = ReactElement<TableFieldProps<T>, typeof TableField>
export function Table<T>({ data, children }: TableProps<T>) {
return (<table/>)
}
The compiler options of typescript look like this:
{
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2021",
"module": "esnext",
"jsx": "react-jsx",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
