Skip to content

[react] React 18 types#56210

Merged
typescript-bot merged 29 commits intoDefinitelyTyped:masterfrom
eps1lon:feat/react/18-breaking
Apr 7, 2022
Merged

[react] React 18 types#56210
typescript-bot merged 29 commits intoDefinitelyTyped:masterfrom
eps1lon:feat/react/18-breaking

Conversation

@eps1lon
Copy link
Copy Markdown
Collaborator

@eps1lon eps1lon commented Oct 5, 2021

Overwhelmed by compile errors after upgrading to @types/react@^18.0.0? Check out https://github.com/eps1lon/types-react-codemod.

Upgrading to React 18 with TypeScript

Breaking Changes

Removal of implicit children

For components that do implement children but relied on their implicit declaration from React.FunctionComponent or React.Component:

 interface Props {
+  children?: React.ReactNode;
 }

 class SomeClassComponents React.Component<Props> {
   render() {
     return  <div>{this.props.children}</div>
   }
 }
 const SomeFunctionComponent: React.FunctionComponent<Props> = props => <div>{props.children}</div>

Please check Removal Of Implicit Children for the rationale.
I may have a solution to bring these back on-demand without patching the published types (watch #59751)

Remove {} from ReactFragment

This was never correct and mostly required to interop with implicit children.

this.context becomes unknown

Was any before. The community mostly prefers unknown by default (any would silently be unsound).

Restore old behavior:

 class Component extends React.Component {
+ context: any;
   render() {
     return this.context.value;
   }
 }

### `noImplicitAny` and `useCallback`

Enabling `noImplicitAny` in `tsconfig` (on by default with `strict: true`) will not type-check if an explicit type is omitted in `useCallback`.

```diff
+ // @ts-expect-error -- `event` as implicitly type 'any'
 useCallback((event) => {})

Remove deprecated types

Bringing the terminology more in line with how they're called in the React docs and repository.

-StatelessComponent
+FunctionComponent

-SFC
+FC

-React.ReactType
+React.ElementType

-SFCElement
+FunctionComponentElement

// no replacement
-Props
-RefForwardingComponent
-SFCFactory

Issues

Closes #46691
Closes #34237
Closes #56026
Closes #52873

Follow-up:

This was referenced Oct 5, 2021
@raegen
Copy link
Copy Markdown

raegen commented Jul 3, 2023

Considering the pivotal argument for the implicit children change is that all the other excess props are rejected so why would we treat children any differently.
How about the fact that no other prop, excess or not, is accessed, processed, handled in any particular way by react, yet children is?
How about the fact that furthermore, children prop has some very specific rules it must abide, depending on its type - the scope of key prop are ultimately siblings, yet it is enforced through children?
How about the fact that no other prop is explicitly frozen (Object.freeze) yet children is?
How about the fact that no other prop facilitates construction of the DOM tree nor attachment to it?

Screenshot 2023-07-03 at 22 14 13

I get it. You like it simple, generic, elegant. Exceptions hurt, are ugly and nobody likes them. But the thing is, whether we like them or not doesn't change the actual engine this is supposed to annotate and it is this exact change that makes children implicit. It blatantly ignores and obfuscates behaviour that's an integral part of the API. Apart from that, the only purpose this served was that of an impediment to updating react to 18.

This whole endeavour is quite simply flabberghasting.

@Hypnosphi
Copy link
Copy Markdown

Hypnosphi commented Jul 4, 2023

Still, if your component doesn't use children prop in any way, passing it should be an error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Check Config Changes a module config files Critical package Edits multiple packages Huge Change Maintainer Approved Self Merge This PR can now be self-merged by the PR author or an owner Too Many Owners

Projects

None yet