chore: [TS] Transform TouchableOpacity from class to ForwardRef component (#44030)

Summary:
If you check the source of truth `packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js` I'll find that `TouchableOpacity` is a result of `React.forwardRef(...)` :

https://github.com/facebook/react-native/blob/f7eaf63881b23216c06ab3c81ea94d0312cd6a7b/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js#L326-L335

So the TS type isn't correct : (

```tsx
<TouchableOpacity ref={ref => {   }} />
//                     ^^^ ref should be a `View` (but now it's `TouchableOpacity`)
```

 ---

**Breaking  changes**

As `TouchableOpacity` isn't class anymore it can't be used as value & type

```tsx
import {TouchableOpacity} from 'react-native';
const ref = useRef<TouchableOpacity>();
//                ^^^ TS2749: TouchableOpacity refers to a value, but is being used as a type here.
//                            Did you mean typeof TouchableOpacity?
```

**Recommend solution:** use build-in react type `React.ElementRef`

```diff
-const ref = useRef<TouchableOpacity>();
+const ref = useRef<React.ElementRef<typeof TouchableOpacity>>();
```

Also, it possible to use `View` as type:

```diff
-const ref = useRef<TouchableOpacity>();
+const ref = useRef<View>();
```

## Changelog:

[GENERAL] [BREAKING] - [Typescript] Transform `TouchableOpacity` from JS `class` to `ForwardRef` component

Pull Request resolved: https://github.com/facebook/react-native/pull/44030

Test Plan: See: `packages/react-native/types/__typetests__/index.tsx`

Reviewed By: NickGerleman

Differential Revision: D56017133

Pulled By: dmytrorykun

fbshipit-source-id: 58f4c1a14c9b3bd2407ea6c825a90b355acb16bb
This commit is contained in:
D N
2024-04-11 14:15:27 -07:00
committed by Facebook GitHub Bot
parent 46b6453eb6
commit 3d00549399
2 changed files with 21 additions and 15 deletions
@@ -8,10 +8,7 @@
*/
import type * as React from 'react';
import {Constructor} from '../../../types/private/Utilities';
import {TimerMixin} from '../../../types/private/TimerMixin';
import {NativeMethods} from '../../../types/public/ReactNativeTypes';
import {TouchableMixin} from './Touchable';
import {View} from '../../Components/View/View';
import {TouchableWithoutFeedbackProps} from './TouchableWithoutFeedback';
export interface TVProps {
@@ -79,14 +76,6 @@ export interface TouchableOpacityProps
*
* @see https://reactnative.dev/docs/touchableopacity
*/
declare class TouchableOpacityComponent extends React.Component<TouchableOpacityProps> {}
declare const TouchableOpacityBase: Constructor<TimerMixin> &
Constructor<TouchableMixin> &
Constructor<NativeMethods> &
typeof TouchableOpacityComponent;
export class TouchableOpacity extends TouchableOpacityBase {
/**
* Animate the touchable to a new opacity.
*/
setOpacityTo: (value: number) => void;
}
export const TouchableOpacity: React.ForwardRefExoticComponent<
React.PropsWithoutRef<TouchableOpacityProps> & React.RefAttributes<View>
>;
@@ -485,9 +485,26 @@ function TouchableTest() {
}
export class TouchableOpacityTest extends React.Component {
buttonRef = React.createRef<React.ElementRef<typeof TouchableOpacity>>();
render() {
return (
<>
<TouchableOpacity ref={this.buttonRef} />
<TouchableOpacity
ref={ref => {
ref?.focus();
ref?.blur();
ref?.measure(
(x, y, width, height, pageX, pageY): number =>
x + y + width + height + pageX + pageY,
);
ref?.measureInWindow(
(x, y, width, height): number => x + y + width + height,
);
ref?.setNativeProps({focusable: false});
}}
/>
<TouchableOpacity focusable={false} />
<TouchableOpacity rejectResponderTermination={true} />
<TouchableOpacity