Closed
Description
Not sure where to put it, but I have these helper types in my team's codebase to extract the props of a component:
// helper type for all known valid JSX element constructors (class and function based)
type ElementConstructor<P> =
| ((props: P) => React.ReactElement<any> | null)
| (new (props: P) => React.Component<P, any, any>
// gets the internal props of a component
// used like Props<typeof MyComponent>
// or Props<'button'> for intrinsic HTML attributes
type Props<C> = C extends ElementConstructor<infer P>
? P
: C extends keyof JSX.IntrinsicElements
? JSX.InstrinsicElements[C]
: {}
// goes one step further and resolves with propTypes and defaultProps properties
type ApparentProps<C> = C extends ElementConstructor<infer P> ? JSX.LibraryManagedAttributes<C, P> : Props<C>
As far as how we use them, there's a lot of places where I want to reuse some slices of props because of prop drilling, and I can either export the props type as part of the module or I use this (either way works), the advantage of using this is that a refactor of the source of truth component will propagate to all consuming components.
I also use them to strongly type custom event handlers if they're not written at the call sites themselves (i.e. inlined with the JSX attribute):
// my-inner-component.tsx
export function MyInnerComponent(props: { onSomeEvent(event: ComplexEventObj, moreArgs: ComplexArgs): SomeWeirdReturnType }) { /* ... */ }
// my-consuming-component.tsx
export function MyConsumingComponent() {
// event and moreArgs are contextually typed along with the return value
const theHandler: Props<typeof MyInnerComponent>['onSomeEvent'] = (event, moreArgs) => {}
return <MyInnerComponent onSomeEvent={theHandler} />
}