Skip to content

Instantly share code, notes, and snippets.

@cassler
Created August 2, 2022 20:29
Show Gist options
  • Save cassler/5d3a3f09d93b6037167dd89eee0c0035 to your computer and use it in GitHub Desktop.
Save cassler/5d3a3f09d93b6037167dd89eee0c0035 to your computer and use it in GitHub Desktop.
Re-implement a Typescript component with types preserved
import React from 'react';
// This allows us to apply the typings of one component to another without
// having to maintain interfaces or types manually.
export type ExtractProps<T> = T extends React.ComponentType<infer P> ? P : T;
// This can be used to maintain behavior from the original component on our
// library customized version. For example. if we want to customize parts of
// HeadlessUI -- we could repackage their components with preserved types
// and props - like so...
import { Tab as HeadlessTab } from '@headlessui/react';
export function Tab(props: ExtractProps<typeof HeadlessTab>) {
return <HeadlessTab {...props} />;
}
// Pretty simple, right? Now look what happens when we just want to do some
// basic configuration such a default props or styling. This will behave
// exactly the same as `@headlessui/react/Tab - even type definitions.
// First, lets move our typing into its own declaration
// and add a few more properties.
type OurTabProps = ExtractProps<typeof HeadlessTab> & {
arg0: boolean,
arg1: boolean,
arg2: string
};
// Now we have our custom props as well as the entire original API.
export function TabWithClass(props: OurTabProps) {
const { className, ...attr } = props;
const clsx = ['bg-blue-500 p-4 border', className].join(' ');
return <HeadlessTab {...attr} className={clsx} />;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment