Home > OS >  TypeScript React: get rid of TS(2339) when extending a React.FC with a static property of type JSX.E
TypeScript React: get rid of TS(2339) when extending a React.FC with a static property of type JSX.E

Time:09-16

The typescript compiler in VSCode, currently at TypeScript React 4.4.2 points to a TS(2339) error: Property 'Col' does not exist on type 'FC<GridProps>'.

I've tried adding this prop to GridProps:

export type GridProps = {
  children: ReactNode;
  className?: string;
  Col: JSX.Element;
};

But the error still shows. I think this is because the Grid component is not initialized. I've seen this convention of extending a main component with other uninitialized components such as Grid.Col = Col (see the screenshot), and it actually works when it is implemented:

<Grid.Col>
  {/* */}
</Grid.Col>

How to remove the TS(2339) error in this case?

NOTE: I've seen components like these before, the compiler doesn't throw and they don't event specify the Component prop in their prop types.

screenshot that describes the error

enter image description here

CodePudding user response:

First, you need to remove Col in GridProps, Col is not a prop.

export type GridProps = {
  children: ReactNode;
  className?: string;
};

Second, to make TS happy, we need to specify the type of Grid component.

export type GridType = FC<GridProps> & {
  Col: FC<{}>;
};

And the implementation:

export const Grid: GridType = (({ className, children }) => {
  return <div className={className}>{children}</div>;
}) as GridType;

Grid.Col = () => {
  return <p>hello</p>;
};

Demo here:

https://codesandbox.io/s/practical-haze-w3o57?file=/src/App.tsx

Another approach is, using Function, not Arrow Function with React.FC<>.

export type GridProps = {
  children: ReactNode;
  className?: string;
};

export function Grid({ className, children }: GridProps) {
  return <div className={className}>{children}</div>;
}

Grid.Col = () => {
  return <p>hello</p>;
};

https://codesandbox.io/s/optimistic-pike-1ir9i?file=/src/App.tsx

Another approach is, not to use React.FC. You can read more about this here: TypeScript React.FC<Props> confusion

export type GridProps = {
  children: ReactNode;
  className?: string;
};

export const Grid = ({ className, children }: GridProps) => {
  return <div className={className}>{children}</div>;
};

Grid.Col = () => {
  return <p>hello</p>;
};

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <Grid>
        <Grid.Col />
      </Grid>
    </div>
  );
}
  • Related