Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typing required props for as #7

Open
rafgraph opened this issue May 12, 2021 · 5 comments
Open

Typing required props for as #7

rafgraph opened this issue May 12, 2021 · 5 comments

Comments

@rafgraph
Copy link

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>
      */}
    </>
  );
}
@Mesoptier
Copy link

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.

@rafgraph
Copy link
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.

@Mesoptier
Copy link

Mesoptier commented May 13, 2021

@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.

@rafgraph
Copy link
Author

Thanks @Mesoptier, that looks promising!

@Mesoptier
Copy link

@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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants