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

[material-ui] Change React.ReactElement<any> to React.ReactElement<unknown> #43402

Merged
merged 20 commits into from
Oct 3, 2024

Conversation

sai6855
Copy link
Contributor

@sai6855 sai6855 commented Aug 22, 2024

Part of: #42380

follow up on #43358 (review)

As of now, there are 7 instances of React.ReactElement left to be migrated except for base/, joy/ folders. Remaining chnages are not straight forward changes from any to unknown, as those requires few more type changes. i'll open a new PR for left over instances

image

@mui-bot
Copy link

mui-bot commented Aug 22, 2024

Netlify deploy preview

https://deploy-preview-43402--material-ui.netlify.app/

Bundle size report

No bundle size changes (Toolpad)
No bundle size changes

Generated by 🚫 dangerJS against d013bd8

@sai6855 sai6855 marked this pull request as draft August 22, 2024 03:52
@sai6855 sai6855 added typescript React 19 support PRs required to support React 19 labels Aug 22, 2024
@@ -91,7 +91,7 @@ function throwMissingPropError(field: string): never {
* the root component.
*/
export function testClassName(
element: React.ReactElement<any>,
element: React.ReactElement<HTMLElement & { 'data-testid'?: string }>,
Copy link
Contributor Author

@sai6855 sai6855 Aug 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All changes of any to unknown (some were changed to HTMLElement) in this PR are straight forward, except for changes in this file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain the criteria you used to choose the type of element in the different functions? I'm trying to understand the impact it will have on the describeConformance usage. Will elements passed to testClassName without the 'data-tested' prop throw a type error? Where would that error show?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, calling testClassName without passing data-testid is throwing type error.

This is tricky to fix, data-testid is added to element as below.

React.cloneElement(element, { className, 'data-testid': testId }),

I think we have 2 options to fix

  1. add data-testid type to argument as above, but it throws type error when consumers of this function doesn't add data-testid type
  2. Keep element argument type as React.ReactElement<unknown> and type cast element type near it's usage as shown below.
 React.cloneElement(element
+ as React.ReactElement<unknown & {[data-testid]:string}>
, { className, 'data-testid': testId }),
 

By going with option 2 , we can keep types of consumers of this function to be flexible. what do you think?

What i did for now is, i've reverted all changes in this file here, what ever option we choose i'll create a seprate PR as this PR is alread too big and i don't want this descion to block this PR from merging.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's open another PR and discuss it there 👌🏼

I think we can create a type that is the same as ReactElement but supports data- attributes

Copy link
Member

@DiegoAndai DiegoAndai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking this @sai6855, I left some questions

@@ -13,7 +13,7 @@ interface Props {
* You won't need it on your project.
*/
window?: () => Window;
children?: React.ReactElement<any>;
children?: React.ReactElement<unknown & { elevation?: number }>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is & { elevation?: number } needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here elevation prop is added to children, since unknown type doesn't have elevation type, i explicitly added. I'm not entirely sure if this is optimal, but please let me know if you have better suggestion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can have only the elevation prop:

Suggested change
children?: React.ReactElement<unknown & { elevation?: number }>;
children?: React.ReactElement<{ elevation?: number }>;

As unknown is absorbed in intersections:

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type:~:text=//%20In%20an%20intersection%20everything%20absorbs%20unknown

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed here 3ff9828

docs/src/components/typography/SectionHeadline.tsx Outdated Show resolved Hide resolved
@@ -306,7 +306,7 @@ function render(
traceSync('forceUpdate', () =>
testingLibraryRenderResult.rerender(
React.cloneElement(element, {
'data-force-update': String(Math.random()),
['data-force-update' as string]: String(Math.random()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is as string required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here element type is unknown, since unknown doesn't have data-force-update type, i've explicitly marked type as as string

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if I understand correctly, this is casting the key, not the value 🤔

What's the error thrown without the cast?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of casting, i've tried to fix type error properly here =>09f5298

@@ -82,7 +82,7 @@ export interface CreateCssVarsProviderResult<
disableStyleSheetGeneration?: boolean;
}
>,
) => React.ReactElement<any>;
) => React.ReactElement<unknown>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think should this type be @siriwatknp? It's the return value of CssVarsProvider, we should have it's props somewhere, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -8,4 +8,4 @@ export interface GlobalStylesProps<Theme = {}> {

export default function GlobalStyles<Theme = {}>(
props: GlobalStylesProps<Theme>,
): React.ReactElement<any>;
): React.ReactElement<unknown>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@siriwatknp what do you think this type should be?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -91,7 +91,7 @@ function throwMissingPropError(field: string): never {
* the root component.
*/
export function testClassName(
element: React.ReactElement<any>,
element: React.ReactElement<HTMLElement & { 'data-testid'?: string }>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain the criteria you used to choose the type of element in the different functions? I'm trying to understand the impact it will have on the describeConformance usage. Will elements passed to testClassName without the 'data-tested' prop throw a type error? Where would that error show?

@sai6855
Copy link
Contributor Author

sai6855 commented Oct 3, 2024

@DiegoAndai updated PR based on #43402 (comment) #43402 (comment) it is ready for final review

@@ -25,7 +25,7 @@ export interface GlobalStylesProps {
styles: SCGlobalStylesProps<Theme>['styles'];
}

function GlobalStyles(props: GlobalStylesProps): React.ReactElement<any> {
function GlobalStyles(props: GlobalStylesProps): React.ReactElement<unknown> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we should change this one to React.JSX.Element as well.

@@ -25,7 +25,7 @@ export interface GlobalStylesProps {
styles: EmGlobalStylesProps<Theme>['styles'];
}

function GlobalStyles(props: GlobalStylesProps): React.ReactElement<any> {
function GlobalStyles(props: GlobalStylesProps): React.ReactElement<unknown> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we should change this one to React.JSX.Element as well.

@@ -8,4 +8,4 @@ export interface GlobalStylesProps<Theme extends object = {}> {

export default function Global<Theme extends object = {}>(
props: GlobalStylesProps<Theme>,
): React.ReactElement<any>;
): React.ReactElement<unknown>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we should change this one to React.JSX.Element as well.

@DiegoAndai
Copy link
Member

Thanks @sai6855!

@DiegoAndai DiegoAndai merged commit 46869bc into mui:master Oct 3, 2024
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
React 19 support PRs required to support React 19 typescript
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants