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

Once built, polymorphed types become generic "string" types #10

Open
mririgoyen opened this issue Apr 9, 2024 · 4 comments
Open

Once built, polymorphed types become generic "string" types #10

mririgoyen opened this issue Apr 9, 2024 · 4 comments

Comments

@mririgoyen
Copy link

mririgoyen commented Apr 9, 2024

I'm using your package to create polymorphic components that forward refs. Using the following pattern, everything works as intended within the local component library.

import { forwardRef } from 'react';
import { type PolyRefFunction } from 'react-polymorphed';

import { type TypographyProps } from './Typography.props';

const forwardPolymorphicRef = forwardRef as PolyRefFunction;

export const Typography = forwardPolymorphicRef<'span', TypographyProps>(
  (
    {
      align = 'inherit', // This is an enum of 'center | left | right | inherit'
      as,
    }
    ref,
  ) => { ... };

As I said, when used locally, such as in my Storybook examples, TypeScript sees and enforces the types.

Screenshot 2024-04-09 at 10 14 12 AM


However, after building the package with Rollup and importing it into another repository, all the types get genericized. This only happens on components wrapped with this polymorph utility.

Screenshot 2024-04-09 at 10 15 58 AM

Following the types, I see a logical chain to my eventual prop types that are correct.

declare const Typography: react_polymorphed.PolyForwardComponent<"span", TypographyProps, react.ElementType<any, keyof react.JSX.IntrinsicElements>>;

...

interface TypographyProps extends TypographyVariantProps {
    /**
     * Set the text-align on the component.
     * @default inherit
     */
    align?: NonNullable<TypographyVariantProps['align']>;
}

...

type TypographyVariantProps = VariantProps<typeof TypographyVariants>;

...

declare const TypographyVariants: (props?: ({
    align?: "center" | "inherit" | "left" | "right" | null | undefined;
} & class_variance_authority_types.ClassProp) | undefined) => string;

I've traced other components that are not polymorphic and they all follow the same exact pattern, except the first step is a direct call to the React forwardRefExcoticComponent. These all type correctly.

declare const Tooltip: react.ForwardRefExoticComponent<TooltipProps & react.RefAttributes<HTMLDivElement>>;

My question is, am I doing something incorrect at some step that could potentially cause this? Losing type safety on polymorphic components isn't good, so I need to figure out how to resolve this.

@nasheomirro
Copy link
Owner

nasheomirro commented Apr 9, 2024

I haven't really used this package to make another package, but I don't see how that should break things. I guess you could try to check what TypographyProps is first, I'm pretty sure you could also install react-polymorphed in the user-side to check whether we get the same thing:

import { TypographyProps } from "your-package";
import { PolyForwardComponent } from "react-polymorphed";

// test A
declare const props: TypographyProps;
// test if typography props still has the correct 'align' type
props.align = '';

// test B
declare const Test: PolyForwardComponent<'span', TypographyProps>;
// check if it works when used directly
<Test align='left' /> 

Simplest case is both test A and test B failing, if so then most likely rollup is messing up your own types somehow, if both test A and test B succeed then something might have went wrong with rollup figuring out polymorphic components?? If test A succeeds and test B fails then there's something very wrong with this package.

@mririgoyen
Copy link
Author

I haven't really used this package to make another package, but I don't see how that should break things. I guess you could try to check what TypographyProps is first, I'm pretty sure you could also install react-polymorphed in the user-side to check whether we get the same thing:

import { TypographyProps } from "your-package";
import { PolyForwardComponent } from "react-polymorphed";

// test A
declare const props: TypographyProps;
// test if typography props still has the correct 'align' type
props.align = '';

// test B
declare const Test: PolyForwardComponent<'span', TypographyProps>;
// check if it works when used directly
<Test align='left' /> 

Simplest case is both test A and test B failing, if so then most likely rollup is messing up your own types somehow, if both test A and test B succeed then something might have went wrong with rollup figuring out polymorphic components?? If test A succeeds and test B fails then there's something very wrong with this package.

Thanks for the response. I'm going to set up and test each of these cases. I will report back with my findings.

@mririgoyen
Copy link
Author

mririgoyen commented Apr 9, 2024

Both tests pass. I suppose I will start debugging Rollup now.

Screenshot 2024-04-09 at 2 01 34 PM

@adrienrn
Copy link

adrienrn commented Nov 4, 2024

This is an issue I encounter too at the moment.

I'm using this lib as part of my UI component library. These component get built (using vite) and published as a NPM package. Tests within the library work like a charm. However, when using the library in my app, I get errors like follows:

image
Property 'href' does not exist on type 'IntrinsicAttributes & Omit<{}, "as" | keyof ClassAttributes<HTMLSpanElement> | keyof HTMLAttributes<HTMLSpanElement> | "accent" | "textWrap" | "variant"> & ClassAttributes<...> & HTMLAttributes<...> & { ...; } & { ...; }'. Did you mean 'ref'?

I do not expect you to be able to debug this with this limited context. I'm merely trying to raise the issue.

I will investigate the produced types and see if I can identify anything.

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

3 participants