-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Slow Performance with Type Inference on JSX Element #43717
Comments
Quick update, I have changed the implementation to: type Join<T, U> = T & Omit<U, keyof T>;
type As = React.ElementType;
type AsProps<T extends As> = React.ComponentPropsWithoutRef<T>;
type WithAs<T extends As> = Join<{ as: T }, AsProps<T>>;
type WithChildren = {
children?: React.ReactNode;
};
type BoxProps<T extends As> = WithAs<T> & WithChildren;
function Box<T extends As>({ as, children, ...properties }: BoxProps<T>) {
return React.createElement(as, properties, children);
}
export default function App() {
return (
<Box as="a" href="#">
Hello, world!
</Box>
);
} This is based on the Chakra UI implementation and it appears to significantly speed up the validation and auto-completion. It also does not work if you exclude Even when simplified to: type BoxProps<T extends As> = { as: T } & Omit<React.ComponentPropsWithoutRef<T>, never>; As soon as the |
Check times: It seems pretty stable both before and after. Note that even 3.7 is pretty slow for this amount of code. |
#41821 doesn't help. |
Oh sorry, I should've mentioned it is less of a performance regression, but more of an area for improvement since this pattern appears quite popular in several popular React component libraries. I will look into #41821, it does look similar. Also, did you have any idea why omission of |
No worries, checking for regressions is just a normal part of perf investigations. Just to set expectations, I'm not very familiar with these types, so you'll need to be more specific with your question about emit. I tried using your second implementation with the replacement for Edit: I forgot to remove the |
Here's a simpler version, but I still don't know why there's an error: type ComponentProps<T extends "symbol"> =
T extends string
? JSX.IntrinsicElements[T]
: never;
function F<T extends "symbol">(p1: Pick<ComponentProps<T>, keyof ComponentProps<T>>, p2: ComponentProps<T>) {
p1 = p2; // Fine
p2 = p1; // Error
} |
For my simplified version, at least, I believe the issue is that the compiler is not taking advantage of the fact that So that explains why |
That is really weird, thank you for looking into this issue. I think I follow your logic, if |
Dunno why or how, but for me I just picked the intrinsic elements that I am most likely to use and that fixed the sluggish performance type Elements = Pick<
JSX.IntrinsicElements,
'a' | 'div' | 'button' | 'span' | 'article' | 'form' | 'input'
>; |
Taking a look at this in 5.4, I added 300 lines of this to the project void <Box element="a" href="#"></Box>; and check time was 1.44 seconds. Going from 300 lines of it to ~6,000 lines of it, the check time increased to 4.32 seconds, implying a per-element cost of 0.48ms. That seems a little on the high side but not really in the "defect" level of performance considering that |
This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
Version
TypeScript 4.2.4
TypeScript 4.3.0-dev.20210417
Expected Behaviour
Any changes made to the
Box
component have fast validation and auto-completion for associated attributes.Actual Behaviour
TypeScript validation and auto-completion is slow.
Description
I have been investigating the current trend to create a generic React element which will pass through an
element
property and associated attributes and callReact.createElement
. An approach similar to this is used by several prominent projects such as Material UI and Github Primer. I wanted to ensure that TypeScript will infer the correct attributes from the givenelement
property. The code I wrote does work, however it does appear to have a significant performance impact.Related
This issue may be related to these issues: #34801, #43485, #42010, #14729, #38583.
Example
A small, reproducible example can be found at: https://github.com/scottwillmoore/react-box. You can also experiment with it in CodeSandbox. The CodeSandbox version has some differences.
The meat of the TypeScript can be seen below:
The text was updated successfully, but these errors were encountered: