Skip to content

Instantly share code, notes, and snippets.

@tiagobnobrega
Created February 7, 2024 10:49
Show Gist options
  • Save tiagobnobrega/f93c10f1b6dfa49e506976c780ac9f6e to your computer and use it in GitHub Desktop.
Save tiagobnobrega/f93c10f1b6dfa49e506976c780ac9f6e to your computer and use it in GitHub Desktop.
React Typescript Subcomponents
import React from 'react';
/**
* Attaches subcomponents to a parent component for use in
* composed components. Example:
*
* <Parent>
* <Parent.Title>abc</Parent.Title>
* <Parent.Body prop1="foobar"/>
* </Parent>
*
*
* This function also sets displayname on the parent component
* and all children component, and has the correct return type
* for typescript.
*
* Usage:
* export const Modal = attachSubComponents(
* "Modal",
* (props: ModalProps) => { ... },
* { Header, Content, Footer, Title, Subtitle, HeroImage, ... }
* );
* @param displayName topLevelComponent's displayName
* @param topLevelComponent the parent element of the composed component
* @param otherComponents an object of child components (keys are the names of the child components)
* @returns the top level component with otherComponents as static properties
*/
export function attachSubComponents<
C extends React.ComponentType<any>,
O extends Record<string, React.ComponentType<any>>,
>(displayName: string, topLevelComponent: C, otherComponents: O): C & O {
topLevelComponent.displayName = displayName;
Object.values(otherComponents).forEach(
(component) =>
(component.displayName = `${displayName}.${component.displayName}`),
);
return Object.assign(topLevelComponent, otherComponents);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment