Skip to content

Typing required props for as #7

Description

@rafgraph

Hi, is it possible to type the props that as is required to accept? Without this it is easy to pass in an as prop that is not compatible with the polymorphic component. Thanks.

Using the heading example in the readme (also see this codesandbox for a live reproduction):

// Heading from readme:
function Heading<
  T extends React.ElementType = typeof HeadingDefaultElement
>({ as, color, style, ...restProps }: HeadingProps<T>) {
  const Element: React.ElementType = as || HeadingDefaultElement;
  return <Element style={{ color, ...style }} {...restProps} />;
}

const MyHeading: React.FC<{}> = ({ children }) => <h1>{children}</h1>;

function App() {
  return (
    <>
      <Heading as={MyHeading} color="green">
        This should result in a type error because MyHeading doesn't accept a style prop,
        but typescript thinks it's fine even though it doesn't work.
      </Heading>
      {/* this errors because MyHeading doesn't accept a style prop
        <MyHeading style={{ color: "green" }}>MyHeading</MyHeading>
      */}
    </>
  );
}

Activity

  1. Mesoptier commented on May 12, 2021

    @Mesoptier

    You might have some luck with Typescript's conditional types, but I'm not entirely sure if that'll work.

    You could also try adding a value for the generic parameter (i.e. props type) of React.ElementType in T extends React.ElementType. For example: Heading<P extends { style: any }, T extends React.ElementType<P> = typeof HeadingDefaultElement>.

    These are just ideas however, so you'd have to do some experimenting on your own.

  2. rafgraph commented on May 13, 2021

    @rafgraph
    Author

    Thanks @Mesoptier, I tried your suggestions but wasn't able to get it working with react-polymorphic-types. Here's a codesandbox if you want to try.

  3. Mesoptier commented on May 13, 2021

    @Mesoptier

    @rafgraph I've forked your codesandbox and I think I've figured it out: https://codesandbox.io/s/polymorphic-types-required-props-for-as-forked-fmc7k?file=/src/App.tsx.

    I added the OnlyIfStyleable<T> utility type that only allows elements that accept a style prop by conditionally returning T or never. The important changes are commented and marked with // NEW: ....


    Edit: the error message is lacking and is not very descriptive, so perhaps there could be some improvements to the types that makes the error message nicer.

  4. rafgraph commented on May 14, 2021

    @rafgraph
    Author

    Thanks @Mesoptier, that looks promising!

  5. Mesoptier commented on May 21, 2021

    @Mesoptier

    @rafgraph Did you manage to get my solution working in your project?

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions