Render prop API?
See original GitHub issueThere are missing props in the TypeScript type declaration file for ListItem, and also these types should ideally be generics.
- I have searched the issues of this repository and believe that this is not a duplicate.
Expected Behavior
It should be possible to use the ContainerComponent
and ContainerProps
props of the ListItem
component from TypeScript. Also, I expected that ListItem
and MenuItem
would be generic types to account for the fact that any additional props are passed to the component specified by the component
prop, but they’re not. To be specific, in this file, the interface is currently defined like this:
export interface MenuListProps ...
whereas I would have expected to see something like this:
export interface MenuListProps<TContainerComponentProps = {}> ...
Current Behavior
This TypeScript (.tsx) code does not compile:
<ListItem ContainerComponent="div" ContainerProps={{className: 'demo'}}>an item</ListItem>
Steps to Reproduce (for bugs)
Create the following test component in TypeScript:
import React from 'react'
import { ListItem, ListItemProps } from 'material-ui/List'
const Test: React.SFC<{}> = () => {
return <ListItem ContainerComponent="div" ContainerProps={{className: 'demo'}}>an item</ListItem>
}
export default Test
Notes
The priority here is adding ContainerComponent
and ContainerProps
to the type declaration. Making it generic (e.g. MenuListProps<TContainerComponentProps = {}>
) is arguably a best practice and would be nice, but might not be so practically useful in this case. If it were a class component it might be more helpful, but as far as I can tell, TypeScript does not provide a way to alias generic functions that would be any more concise than my current solution of using a typecast:
const MyMenuItem = MenuItem as React.ComponentType<MenuItemProps & MyComponentProps>
...
render() {
return <MyMenuItem component={MyComponent} somePropToMyComponent="demo">an item</MyMenuItem>
}
Your Environment
Tech | Version |
---|---|
Material-UI | 1.0.0-beta.32 |
React | 16.2.0 |
browser | Chrome 64 |
TypeScript | 2.7.1 |
Issue Analytics
- State:
- Created 6 years ago
- Comments:27 (19 by maintainers)
Top GitHub Comments
For generic props to be useful you also need generic components, and unfortunately those aren’t well supported currently; see https://github.com/Microsoft/TypeScript/issues/6395.
I think this is fine, albeit not as type safe as one could hope:
@oliviertassinari as a larger design note, the
FooComponent
/FooProps
pattern that’s common in Material UI presents a tricky problem for making type safe. It would be much easier and more powerful if we just used render props for these situations, e.g.Here you can be very specific about the props (
{ className: string; children: ReactNode }
) because you know that’s exactly what will be passed, and it’s up to the provider of the render prop to render that however they see fit. They can use whatever root element they want, whatever attributes they want, and even add more children. It allows complete customization while remaining perfectly type safe.If you just extract it to a variable in the render method, you haven’t saved anything; it will still be a new component on every render. And if
someAdditionalFlag
is something that had to be computed from the props, you can’t defineC
at the module level. You’re forced to make your component into a class if it wasn’t already, withC
a field on it (see example above).