Skip to content

Instantly share code, notes, and snippets.

@benmvp
Last active January 17, 2020 18:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benmvp/a80b841cc962d0251460098d3ff3bf61 to your computer and use it in GitHub Desktop.
Save benmvp/a80b841cc962d0251460098d3ff3bf61 to your computer and use it in GitHub Desktop.
Trying to extend my Text component props from the props that come from the specified HTML element using TypeScript generics
import React from 'react'
// React.ElementType from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/8a31a2fe9e8417d47550db09e5f9f50fd09a8e60/types/react/index.d.ts#L67
interface Props<C extends React.ElementType> {
children: React.ReactNode
component?: C;
gutterBottom?: boolean;
className?: string;
style?: CSSProperties;
}
type TextProps<C extends React.ElementType> = Props<C> & Exclude<React.ComponentPropsWithRef<C>, Props<C>>;
// Text is set up to act like a superset of the component specified
const Text = <C extends React.ElementType>({
children,
component,
gutterBottom,
...additionalAttributes
// Typing the props as TextProps<C> below doesn't work. `component` comes up as `any`
}: TextProps<C>) => {
// However, picking a specific element (such as `'label'` works and I can access `component.gutterBottom`
// }: TextProps<'label'>) => {
const Component = component || 'span'
return <Component {...additionalAttributes}>{children}</Component>
}
@benmvp
Copy link
Author

benmvp commented Jan 17, 2020

And I figured it out!

This line:

type TextProps<C extends React.ElementType> = Props<C> & Exclude<React.ComponentPropsWithRef<C>, Props<C>>;

should've been:

type TextProps<C extends ElementType> = Props<C> & Omit<React.ComponentPropsWithRef<C>, keyof Props<C>>;

I should've used Omit<T, K> instead of Exclude<T, U>. Although I never got an error explaining this, my guess is that since children, className & style already exist on HTML elements, having them be duplicated when doing the intersection (&) was causing problems. I had done Exclude<T, U> to remove the dupes, but that wasn't actually doing what I thought it was. I needed to remove the dupe keys using Omit<T, K> and keyof 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment