react-polymorphic-box icon indicating copy to clipboard operation
react-polymorphic-box copied to clipboard

Incorrect work with Unions Types

Open SiarheiLazakovich opened this issue 4 years ago • 2 comments

Description

Polymorphic box has partialized props if "as" component has unioned props.

Reproduction

import React from 'react';
import { Box } from 'react-polymorphic-box';

interface ITestA {
  value: 'a';
}

interface ITestB {
  value: 'b';
  extra: string;
}

type Test = ITestA | ITestB;

const Test: React.FC<Test> = (props) => {
  return <></>;
};

function App() {
  return (
    <>
      <Test value="b" extra="extra" />
      <Box as={Test} value="b" extra="extra" />
    </>
  );
}

Expected behavior

Polymorphic box has correct props types.

Actual behavior

Type '{ as: FC<Test>; value: "b"; extra: string; }' is not assignable to type 'IntrinsicAttributes & BoxOwnProps<FC<Test>> & Pick<PropsWithChildren<Test>, "value" | "children">'. Property 'extra' does not exist on type 'IntrinsicAttributes & BoxOwnProps<FC<Test>> & Pick<PropsWithChildren<Test>, "value" | "children">'

SiarheiLazakovich avatar Jan 05 '21 11:01 SiarheiLazakovich

Thank you for your report!

Please try specifying the union as follows and get back to me whether it works or not:

interface ITestA {
  value: 'a';
  extra?: never; // Inspired by https://github.com/vercel/next.js/blob/51f2a530d623f4b50e71ce849e4276d2fea28211/packages/next/client/image.tsx#L63-L74
}

interface ITestB {
  value: 'b';
  extra: string;
}

type Test = ITestA | ITestB;

kripod avatar Jan 05 '21 22:01 kripod

Thank you for your fast response)

this workaround is not perfect:

import React from 'react';
import { Box } from 'react-polymorphic-box';

interface ITestA {
  value: 'a';
  extra?: string;
}

interface ITestB {
  value: 'b';
  extra: string;
}

type Test = ITestA | ITestB;

const Test: React.FC<Test> = (props) => {
  return <></>;
};

function App() {
  return (
    <>
      <Test value="b" />
      <Box as={Test} value="b" />
    </>
  );
}

I expect that "Box" has the same error.

error:

Type '{ value: "b"; }' is not assignable to type '(IntrinsicAttributes & ITestA & { children?: ReactNode; }) | (IntrinsicAttributes & ITestB & { children?: ReactNode; })'. Property 'extra' is missing in type '{ value: "b"; }' but required in type 'ITestB'.ts(2322)

SiarheiLazakovich avatar Jan 06 '21 05:01 SiarheiLazakovich