Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to infer component props with base component assignment

I am trying to create a component library and would like to take advantage of as prop in it (like react-bootstrap). However, I am struggling with TypeScript and I have no idea how to make it infer the correct types for the selected property. I would like to make the intrinsic elements work too.

What I have is the following:


import React from "react";

export type AsProp<As extends React.ElementType> = {
  as?: As
} & React.ComponentPropsWithoutRef<As>;

type TestProps<As extends React.ElementType = 'div'> = AsProp<As> & {
  active: boolean
}

export const TestComponent: React.FC<TestProps> = props => {
  const {as: Component = 'div', ...rest} = props;

  return <Component {...rest} />;
}

export const UsageComponent = () => {
  return <TestComponent as='a' href='asd' active/>;
}


It seems like my code does not infer the as prop and i get the following error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

TS2322: Type '"a"' is not assignable to type '"div" | undefined'.

How can I fix it so it infers it correctly instead of forcing me to use the default type?

>Solution :

When you do this:

export const TestComponent: React.FC<TestProps> = props => {

You declare TestProps without its generic parameter, so the default 'div' is used. So to make this work TestComponent must be generic as well. An I would argue that function is where the default type belongs and NOT the the props type.

type TestProps<As extends React.ElementType> = AsProp<As> & {
  active: boolean
}

export function TestComponent<
  As extends React.ElementType = 'div'
>(props: TestProps<As>) {
  const {as: Component = 'div', ...rest} = props;
  return <Component {...rest} />;
}

Playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading