Skip to content

[Suggestion] Extracting props of a component #63

Closed
@ferdaber

Description

@ferdaber

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} />
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    wontfixThis will not be worked on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions