diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts index ec87050c27de..24f632825a84 100644 --- a/packages/react-native/ReactNativeApi.d.ts +++ b/packages/react-native/ReactNativeApi.d.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> * * This file was generated by scripts/js-api/build-types/index.js. */ @@ -1650,10 +1650,10 @@ declare interface ButtonProps { readonly nextFocusRight?: number readonly nextFocusUp?: number readonly onAccessibilityAction?: (event: AccessibilityActionEvent) => unknown + readonly onPress?: (event?: GestureResponderEvent) => unknown readonly testID?: string readonly title: string readonly touchSoundDisabled?: boolean - readonly onPress?: (event?: GestureResponderEvent) => unknown } declare function cancelHeadlessTask(taskId: number, taskKey: string): void declare type Category = string @@ -1680,9 +1680,9 @@ declare type CellRendererProps = { readonly children: React.ReactNode readonly index: number readonly item: ItemT - readonly style: StyleProp readonly onFocusCapture?: (event: FocusEvent) => void readonly onLayout?: (event: LayoutChangeEvent) => void + readonly style: StyleProp } declare class CellRenderMask { addCells(cells: { first: number; last: number }): void @@ -2600,12 +2600,12 @@ declare type InterpolationConfigType< OutputT extends InterpolationConfigSupportedOutputType, > = Readonly< AnimatedNodeConfig & { + easing?: (input: number) => number extrapolate?: ExtrapolateType extrapolateLeft?: ExtrapolateType extrapolateRight?: ExtrapolateType inputRange: ReadonlyArray outputRange: ReadonlyArray - easing?: (input: number) => number } > declare type IOSKeyboardEvent = Readonly< @@ -3249,6 +3249,14 @@ declare type OptionalFlatListProps = { end: number start: number } + getItemLayout?: ( + data: Readonly> | undefined, + index: number, + ) => { + index: number + length: number + offset: number + } horizontal?: boolean initialNumToRender?: number initialScrollIndex?: number @@ -3258,14 +3266,6 @@ declare type OptionalFlatListProps = { removeClippedSubviews?: boolean renderItem?: ListRenderItem strictMode?: boolean - getItemLayout?: ( - data: Readonly> | undefined, - index: number, - ) => { - index: number - length: number - offset: number - } } declare type OptionalPlatformSelectSpec = { [key in PlatformOSType]?: T } declare type OptionalSectionListProps = { @@ -3282,6 +3282,14 @@ declare type OptionalVirtualizedListProps = { debug?: boolean disableVirtualization?: boolean extraData?: any + getItemLayout?: ( + data: any, + index: number, + ) => { + index: number + length: number + offset: number + } horizontal?: boolean initialNumToRender?: number initialScrollIndex?: number @@ -3315,29 +3323,17 @@ declare type OptionalVirtualizedListProps = { refreshing?: boolean removeClippedSubviews?: boolean renderItem?: ListRenderItem + renderScrollComponent?: (props: ScrollViewProps) => React.JSX.Element updateCellsBatchingPeriod?: number viewabilityConfig?: ViewabilityConfig viewabilityConfigCallbackPairs?: Array windowSize?: number - getItemLayout?: ( - data: any, - index: number, - ) => { - index: number - length: number - offset: number - } - renderScrollComponent?: (props: ScrollViewProps) => React.JSX.Element } declare type OptionalVirtualizedSectionListProps< ItemT, SectionT = DefaultVirtualizedSectionT, > = { onEndReached?: ($$PARAM_0$$: { distanceFromEnd: number }) => void - renderSectionFooter?: (info: { section: SectionT }) => null | React.ReactNode - renderSectionHeader?: (info: { section: SectionT }) => null | React.ReactNode - SectionSeparatorComponent?: React.ComponentType - stickySectionHeadersEnabled?: boolean renderItem?: (info: { index: number item: ItemT @@ -3348,6 +3344,10 @@ declare type OptionalVirtualizedSectionListProps< updateProps: (select: "leading" | "trailing", newProps: Object) => void } }) => null | React.ReactNode + renderSectionFooter?: (info: { section: SectionT }) => null | React.ReactNode + renderSectionHeader?: (info: { section: SectionT }) => null | React.ReactNode + SectionSeparatorComponent?: React.ComponentType + stickySectionHeadersEnabled?: boolean } declare type OrientationChangeEvent = { readonly orientation: "landscape" | "portrait" @@ -3577,13 +3577,13 @@ declare type PressabilityConfig = { readonly pressRectOffset?: RectOrSize } declare type PressabilityEventHandlers = { - readonly onBlur: (event: BlurEvent) => void - readonly onClick: (event: GestureResponderEvent) => void - readonly onFocus: (event: FocusEvent) => void readonly onMouseEnter?: (event: MouseEvent) => void readonly onMouseLeave?: (event: MouseEvent) => void readonly onPointerEnter?: (event: PointerEvent) => void readonly onPointerLeave?: (event: PointerEvent) => void + readonly onBlur: (event: BlurEvent) => void + readonly onClick: (event: GestureResponderEvent) => void + readonly onFocus: (event: FocusEvent) => void readonly onResponderGrant: (event: GestureResponderEvent) => boolean | void readonly onResponderMove: (event: GestureResponderEvent) => void readonly onResponderRelease: (event: GestureResponderEvent) => void @@ -4229,6 +4229,14 @@ declare type ScrollViewBaseProps = { readonly autoscrollToTopThreshold?: number readonly minIndexForVisible: number } + readonly onContentSizeChange?: ( + contentWidth: number, + contentHeight: number, + ) => void + readonly onKeyboardDidHide?: (event: KeyboardEvent) => void + readonly onKeyboardDidShow?: (event: KeyboardEvent) => void + readonly onKeyboardWillHide?: (event: KeyboardEvent) => void + readonly onKeyboardWillShow?: (event: KeyboardEvent) => void readonly onMomentumScrollBegin?: (event: ScrollEvent) => void readonly onMomentumScrollEnd?: (event: ScrollEvent) => void readonly onScroll?: (event: ScrollEvent) => void @@ -4249,14 +4257,6 @@ declare type ScrollViewBaseProps = { readonly StickyHeaderComponent?: StickyHeaderComponentType readonly stickyHeaderHiddenOnScroll?: boolean readonly stickyHeaderIndices?: ReadonlyArray - readonly onContentSizeChange?: ( - contentWidth: number, - contentHeight: number, - ) => void - readonly onKeyboardDidHide?: (event: KeyboardEvent) => void - readonly onKeyboardDidShow?: (event: KeyboardEvent) => void - readonly onKeyboardWillHide?: (event: KeyboardEvent) => void - readonly onKeyboardWillShow?: (event: KeyboardEvent) => void } declare type ScrollViewComponentStatics = { readonly Context: typeof $$ScrollViewContext @@ -4329,13 +4329,13 @@ declare type ScrollViewPropsIOS = { readonly indicatorStyle?: "black" | "default" | "white" readonly maximumZoomScale?: number readonly minimumZoomScale?: number + readonly onScrollToTop?: (event: ScrollEvent) => void readonly pinchGestureEnabled?: boolean readonly scrollIndicatorInsets?: EdgeInsetsProp readonly scrollsToTop?: boolean readonly scrollToOverflowEnabled?: boolean readonly showsHorizontalScrollIndicator?: boolean readonly zoomScale?: number - readonly onScrollToTop?: (event: ScrollEvent) => void } declare interface ScrollViewScrollToOptions { animated?: boolean @@ -4359,6 +4359,10 @@ declare type SectionBase< data: ReadonlyArray ItemSeparatorComponent?: React.ComponentType | React.JSX.Element key?: string + keyExtractor?: ( + item: SectionItemT | undefined, + index?: number | undefined, + ) => string renderItem?: (info: { index: number item: SectionItemT @@ -4369,10 +4373,6 @@ declare type SectionBase< updateProps: (select: "leading" | "trailing", newProps: Object) => void } }) => null | React.JSX.Element - keyExtractor?: ( - item: SectionItemT | undefined, - index?: number | undefined, - ) => string } declare class SectionList< ItemT = any, @@ -4504,6 +4504,17 @@ declare type ShareOptions = { } declare interface Spec extends TurboModule { readonly blur?: (reactTag: number) => void + readonly focus?: (reactTag: number) => void + readonly getConstantsForViewManager?: ( + viewManagerName: string, + ) => Object | undefined + readonly getDefaultEventTypes?: () => Array + readonly lazilyLoadView?: (name: string) => Object + readonly sendAccessibilityEvent?: ( + reactTag: number, + eventType: number, + ) => void + readonly setLayoutAnimationEnabledExperimental?: (enabled: boolean) => void readonly clearJSResponder: () => void readonly configureNextLayoutAnimation: ( config: Object, @@ -4532,13 +4543,7 @@ declare interface Spec extends TurboModule { height: number, ) => void, ) => void - readonly focus?: (reactTag: number) => void readonly getConstants: () => Object - readonly getConstantsForViewManager?: ( - viewManagerName: string, - ) => Object | undefined - readonly getDefaultEventTypes?: () => Array - readonly lazilyLoadView?: (name: string) => Object readonly manageChildren: ( containerTag: number, moveFromIndices: Array, @@ -4571,16 +4576,11 @@ declare interface Spec extends TurboModule { height: number, ) => void, ) => void - readonly sendAccessibilityEvent?: ( - reactTag: number, - eventType: number, - ) => void readonly setChildren: (containerTag: number, reactTags: Array) => void readonly setJSResponder: ( reactTag: number, blockNativeResponder: boolean, ) => void - readonly setLayoutAnimationEnabledExperimental?: (enabled: boolean) => void readonly updateView: ( reactTag: number, viewName: string, @@ -5166,6 +5166,7 @@ declare type TimingAnimationConfig = Readonly< AnimationConfig & { delay?: number duration?: number + easing?: (value: number) => number toValue: | AnimatedColor_default | AnimatedInterpolation_default @@ -5177,7 +5178,6 @@ declare type TimingAnimationConfig = Readonly< readonly x: number readonly y: number } - easing?: (value: number) => number } > declare type ToastAndroid = typeof ToastAndroid @@ -5699,22 +5699,22 @@ export { AccessibilityActionEvent, // a0d4daa0 AccessibilityActionInfo, // db47a917 AccessibilityInfo, // 23a3aa9b - AccessibilityProps, // 21f32d3a + AccessibilityProps, // eda80653 AccessibilityRole, // f2f2e066 AccessibilityState, // b0c2b3f7 AccessibilityValue, // cf8bcb74 ActionSheetIOS, // b558559e ActionSheetIOSOptions, // 1756eb5a - ActivityIndicator, // 0f796809 + ActivityIndicator, // e43c68bb ActivityIndicatorInstance, // a82dd4e7 - ActivityIndicatorProps, // a232e3ff - Alert, // 5bf12165 + ActivityIndicatorProps, // 619842eb + Alert, // a398a509 AlertButton, // bf1a3b60 AlertButtonStyle, // ec9fb242 - AlertOptions, // a0cdac0f + AlertOptions, // 8a116d2a AlertType, // 5ab91217 AndroidKeyboardEvent, // e03becc8 - Animated, // 91a7b171 + Animated, // 50cbe576 AppConfig, // 35c0ca70 AppRegistry, // 1e8c5a00 AppState, // 12012be5 @@ -5728,9 +5728,9 @@ export { BackPressEventName, // 4620fb76 BlurEvent, // 4ba4f941 BoxShadowValue, // b679703f - Button, // 2e36a068 - ButtonInstance, // 0a11787b - ButtonProps, // 4a8a20e3 + Button, // bc8f6464 + ButtonInstance, // d94b4241 + ButtonProps, // 21c5780c Clipboard, // 41addb89 CodegenTypes, // ab4986cc ColorSchemeName, // 6615edd6 @@ -5748,9 +5748,9 @@ export { DimensionsPayload, // 653bc26c DisplayMetrics, // 1dc35cef DisplayMetricsAndroid, // 872e62eb - DrawerLayoutAndroid, // a8ced056 + DrawerLayoutAndroid, // 7843b7b5 DrawerLayoutAndroidInstance, // c0694352 - DrawerLayoutAndroidProps, // e9a67dd7 + DrawerLayoutAndroidProps, // 0c1d6155 DrawerSlideEvent, // c4ab8fba DropShadowValue, // e9df2606 DynamicColorIOS, // d96c228c @@ -5766,39 +5766,39 @@ export { EventSubscription, // b8d084aa ExtendedExceptionData, // 5a6ccf5a FilterFunction, // bf24c0e3 - FlatList, // 0f2531c9 - FlatListInstance, // f31d4744 - FlatListProps, // b8b5adf2 + FlatList, // e1b005c7 + FlatListInstance, // 2d1d8e45 + FlatListProps, // 94fa2dc7 FocusEvent, // 850f1517 FontVariant, // 7c7558bb GestureResponderEvent, // 14d3e77a - GestureResponderHandlers, // c976c2ea + GestureResponderHandlers, // b540de80 HostComponent, // a611806a HostInstance, // f78dcaf8 I18nManager, // f9870e00 IEventEmitter, // fbef6131 IOSKeyboardEvent, // e67bfe3a IgnorePattern, // ec6f6ece - Image, // fba54a35 - ImageBackground, // 1543bae2 - ImageBackgroundInstance, // 610d9eed - ImageBackgroundProps, // ceb153c3 + Image, // 87b793a4 + ImageBackground, // abfd6c1d + ImageBackgroundInstance, // 50bc4cb3 + ImageBackgroundProps, // e04f173a ImageErrorEvent, // 978933f4 ImageInstance, // 9a100753 ImageLoadEvent, // 77f0b718 ImageProgressEventIOS, // 445331a4 - ImageProps, // e8aecf89 - ImagePropsAndroid, // 9fd9bcbb - ImagePropsBase, // f5535cef - ImagePropsIOS, // 4a080668 + ImageProps, // c50cfe0d + ImagePropsAndroid, // ee00e1d5 + ImagePropsBase, // fa3f8e21 + ImagePropsIOS, // 9e19c85d ImageRequireSource, // 681d683b ImageResizeMode, // d51106e2 ImageResolvedAssetSource, // f3060931 ImageSize, // 1c47cf88 - ImageSource, // 48c7f316 - ImageSourcePropType, // bfb5e5c6 + ImageSource, // ea31cf4a + ImageSourcePropType, // f522e093 ImageStyle, // 4b7c1906 - ImageURISource, // 016eb083 + ImageURISource, // 443d047c InputAccessoryView, // 9695d393 InputAccessoryViewProps, // d94dc290 InputModeOptions, // 4e8581b9 @@ -5807,9 +5807,9 @@ export { KeyEvent, // 20fa4267 KeyUpEvent, // 57f832c5 Keyboard, // 49414c97 - KeyboardAvoidingView, // cf0307d2 - KeyboardAvoidingViewInstance, // c4ca43a7 - KeyboardAvoidingViewProps, // cf148633 + KeyboardAvoidingView, // fbf69b90 + KeyboardAvoidingViewInstance, // f6c63fc9 + KeyboardAvoidingViewProps, // 8609524c KeyboardEvent, // c3f895d4 KeyboardEventEasing, // af4091c8 KeyboardEventName, // 59299ad6 @@ -5834,12 +5834,12 @@ export { MeasureInWindowOnSuccessCallback, // a285f598 MeasureLayoutOnSuccessCallback, // 3592502a MeasureOnSuccessCallback, // 82824e59 - Modal, // 43f50013 - ModalBaseProps, // ac3931ad + Modal, // 252d448a + ModalBaseProps, // c294cc46 ModalInstance, // d466ce77 - ModalProps, // 35252d68 + ModalProps, // 757e7cec ModalPropsAndroid, // 515fb173 - ModalPropsIOS, // 0e13cfcc + ModalPropsIOS, // 664ecb7e ModeChangeEvent, // f64bf69d MouseEvent, // d1f889fd NativeAppEventEmitter, // 08d4c47d @@ -5857,10 +5857,10 @@ export { Networking, // bbc5be42 OpaqueColorValue, // 25f3fa5b PackagerAsset, // d1c88cf4 - PanResponder, // f8f71cac - PanResponderCallbacks, // 6d63e7be + PanResponder, // e4df325a + PanResponderCallbacks, // c3dafe87 PanResponderGestureState, // 54baf558 - PanResponderInstance, // 69cebbe8 + PanResponderInstance, // 8ccc05bf Permission, // 08f1c82f PermissionStatus, // 4b7de97b PermissionsAndroid, // 8a0bc8d8 @@ -5871,17 +5871,17 @@ export { PlatformSelectSpec, // 09ed7758 PointValue, // 69db075f PointerEvent, // ff599afe - PressabilityConfig, // faab5639 - PressabilityEventHandlers, // 0b910091 - Pressable, // f4911021 + PressabilityConfig, // fea539a5 + PressabilityEventHandlers, // c222648b + Pressable, // 7008c06f PressableAndroidRippleConfig, // ee32eaca PressableInstance, // eebfe911 - PressableProps, // 95d57db2 + PressableProps, // d6bfa55b PressableStateCallbackType, // 9af36561 ProcessedColorValue, // 33f74304 - ProgressBarAndroid, // 3625ddf0 + ProgressBarAndroid, // 2dd6dbfd ProgressBarAndroidInstance, // ab545ef1 - ProgressBarAndroidProps, // f20ebde5 + ProgressBarAndroidProps, // 07fa83a1 PublicRootInstance, // 8040afd7 PublicTextInstance, // 6937c7bf PushNotificationEventName, // 84e7e150 @@ -5889,10 +5889,10 @@ export { PushNotificationPermissions, // c2e7ae4f Rationale, // 5df1b1c1 ReactNativeVersion, // abd76827 - RefreshControl, // 5b3465d2 - RefreshControlInstance, // 8b4d078b - RefreshControlProps, // f8883f9a - RefreshControlPropsAndroid, // 99f64c97 + RefreshControl, // 947cb880 + RefreshControlInstance, // 55f1814a + RefreshControlProps, // eb2b1cbe + RefreshControlPropsAndroid, // 8ac931ca RefreshControlPropsIOS, // 72a36381 Registry, // 6c39216d ResponderSyntheticEvent, // ebfa7f48 @@ -5903,26 +5903,26 @@ export { RootViewStyleProvider, // 8792d506 Runnable, // 594dd93a Runnables, // 4367c557 - SafeAreaView, // 47b1ede1 + SafeAreaView, // 9ce03f75 SafeAreaViewInstance, // 21dba39c ScaledSize, // 07e417c7 ScrollEvent, // d7abdd0a - ScrollResponderType, // 079145bb + ScrollResponderType, // ba188eae ScrollToLocationParamsType, // d7ecdad1 - ScrollView, // d7defbe2 - ScrollViewImperativeMethods, // d3ff1532 - ScrollViewInstance, // 1ba64600 - ScrollViewProps, // 9207390b - ScrollViewPropsAndroid, // 44210553 - ScrollViewPropsIOS, // da991b9a + ScrollView, // 066a8597 + ScrollViewImperativeMethods, // 904c66fd + ScrollViewInstance, // ccf4f341 + ScrollViewProps, // b62913d1 + ScrollViewPropsAndroid, // 02f3df2e + ScrollViewPropsIOS, // 807cb4f6 ScrollViewScrollToOptions, // 3313411e - SectionBase, // dca83594 - SectionList, // f483c886 - SectionListData, // e0d79987 - SectionListInstance, // 1b255509 - SectionListProps, // e06b9868 - SectionListRenderItem, // 466e3e87 - SectionListRenderItemInfo, // d809238e + SectionBase, // 9f13db00 + SectionList, // ee3e7972 + SectionListData, // 1a4de01a + SectionListInstance, // c9b991fe + SectionListProps, // 0e933318 + SectionListRenderItem, // 715b2086 + SectionListRenderItemInfo, // 4a48a922 Separators, // 6a45f7e3 Settings, // 2be0c61e Share, // e4591b32 @@ -5931,72 +5931,72 @@ export { ShareActionSheetIOSOptions, // eff574f5 ShareContent, // 7c627896 ShareOptions, // 800c3a4e - StatusBar, // 81b4e92f + StatusBar, // f95dbb76 StatusBarAnimation, // 7fd047e6 - StatusBarInstance, // 4e03048c - StatusBarProps, // bfedeab1 + StatusBarInstance, // 416e9640 + StatusBarProps, // c2a44d88 StatusBarStyle, // 78f53eea StyleProp, // fa0e9b4a - StyleSheet, // cdddb9ae + StyleSheet, // e734acd4 SubmitBehavior, // c4ddf490 - Switch, // b004beeb + Switch, // f495bab3 SwitchChangeEvent, // 899635b1 SwitchInstance, // 3c50eec5 - SwitchProps, // ded81873 + SwitchProps, // cadfd0c4 Systrace, // 626d178c TVViewPropsIOS, // 330ce7b5 TargetedEvent, // 16e98910 TaskProvider, // 266dedf2 - Text, // f792e51d + Text, // 9ceaff08 TextContentType, // 239b3ecc - TextInput, // 4d0a088b - TextInputAndroidProps, // 7109938a + TextInput, // ce1e41ff + TextInputAndroidProps, // 9ebbc103 TextInputBlurEvent, // b77af40e TextInputChangeEvent, // f55eef98 TextInputContentSizeChangeEvent, // a27cd32a TextInputEndEditingEvent, // e690b56b TextInputFocusEvent, // 19851a88 - TextInputIOSProps, // 0d05a855 + TextInputIOSProps, // fb3c9327 TextInputInstance, // 5a0c0e0d TextInputKeyPressEvent, // 546c5d07 - TextInputProps, // a56c62a0 + TextInputProps, // c692f4de TextInputSelectionChangeEvent, // e58f2abc TextInputSubmitEditingEvent, // 6bcb2aa5 TextInstance, // 05463a96 TextLayoutEvent, // 3f54186f - TextProps, // 58466ea1 + TextProps, // 93309fac TextStyle, // b62b8399 ToastAndroid, // 88a8969a - TouchableHighlight, // 20ba0199 + TouchableHighlight, // 3a6eaed4 TouchableHighlightInstance, // b510c0eb - TouchableHighlightProps, // 337a9164 - TouchableNativeFeedback, // c41fc93f - TouchableNativeFeedbackInstance, // e7895451 - TouchableNativeFeedbackProps, // a645b648 - TouchableOpacity, // 74a1b2c6 + TouchableHighlightProps, // 00e100c4 + TouchableNativeFeedback, // fe739e82 + TouchableNativeFeedbackInstance, // 0877e3e4 + TouchableNativeFeedbackProps, // 1d0c2f30 + TouchableOpacity, // fe716ffc TouchableOpacityInstance, // b186055b - TouchableOpacityProps, // 1d3512ce - TouchableWithoutFeedback, // 61c63ada - TouchableWithoutFeedbackProps, // f4d62822 + TouchableOpacityProps, // a3b32b69 + TouchableWithoutFeedback, // ed159ba7 + TouchableWithoutFeedbackProps, // e613ed05 TransformsStyle, // 65e70f18 TurboModule, // dfe29706 TurboModuleRegistry, // 4ace6db2 - UIManager, // a1a7cc01 + UIManager, // afbcdf05 UTFSequence, // ad625158 Vibration, // 31e4bbf8 - View, // 443391a0 + View, // 3e72139a ViewInstance, // ffde5573 - ViewProps, // 013135a2 - ViewPropsAndroid, // 03c17367 + ViewProps, // 763271bb + ViewPropsAndroid, // 55e81851 ViewPropsIOS, // 58ee19bf ViewStyle, // e45056b1 VirtualViewMode, // 6be59722 VirtualizedList, // 68c7345e VirtualizedListInstance, // 423ee7c0 - VirtualizedListProps, // cc8bc4c9 + VirtualizedListProps, // f51f4a42 VirtualizedSectionList, // 9fd9cd61 VirtualizedSectionListInstance, // 12b706d5 - VirtualizedSectionListProps, // 12a58a4f + VirtualizedSectionListProps, // 8210f30a WrapperComponentProvider, // 9ef54e61 codegenNativeCommands, // 628a7c0a codegenNativeComponent, // 32a1bca6 @@ -6004,10 +6004,10 @@ export { processColor, // 6e877698 registerCallableModule, // 839c8cfe requireNativeComponent, // aa36a6dd - useAnimatedColor, // e3511f81 - useAnimatedValue, // b18adb63 - useAnimatedValueXY, // c7ee2332 + useAnimatedColor, // a9dffd9f + useAnimatedValue, // 25733d13 + useAnimatedValueXY, // 04c70878 useColorScheme, // d585efdb - usePressability, // 095343b5 + usePressability, // 782138ed useWindowDimensions, // bb4b683f } diff --git a/scripts/js-api/build-types/transforms/typescript/__tests__/ensureUndefinedOnOptionalMembers-test.js b/scripts/js-api/build-types/transforms/typescript/__tests__/ensureUndefinedOnOptionalMembers-test.js new file mode 100644 index 000000000000..2214361da192 --- /dev/null +++ b/scripts/js-api/build-types/transforms/typescript/__tests__/ensureUndefinedOnOptionalMembers-test.js @@ -0,0 +1,65 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +const ensureUndefinedOnOptionalMembersVisitor = require('../ensureUndefinedOnOptionalMembers.js'); +const babel = require('@babel/core'); + +async function translate(code: string): Promise { + const result = await babel.transformAsync(code, { + plugins: [ + '@babel/plugin-syntax-typescript', + ensureUndefinedOnOptionalMembersVisitor, + ], + }); + + return result.code; +} + +describe('ensureUndefinedOnOptionalMembers', () => { + test('should add undefined to optional type members', async () => { + const code = ` + type Foo = { + a?: number, + 'b-key'?: number | string, + c?: () => void, + d: boolean, + e: string | undefined, + f?: (() => void) | number, + }; + `; + const result = await translate(code); + expect(result).toMatchInlineSnapshot(` + "type Foo = { + a?: number | undefined; + 'b-key'?: number | string | undefined; + c?: (() => void) | undefined; + d: boolean; + e: string | undefined; + f?: (() => void) | number | undefined; + };" + `); + }); + + test('should not add undefined when already present', async () => { + const code = ` + type Foo = { + a?: number | undefined, + b?: undefined, + }; + `; + const result = await translate(code); + expect(result).toMatchInlineSnapshot(` + "type Foo = { + a?: number | undefined; + b?: undefined; + };" + `); + }); +}); diff --git a/scripts/js-api/build-types/transforms/typescript/__tests__/removeUndefinedFromOptionalMembers-test.js b/scripts/js-api/build-types/transforms/typescript/__tests__/removeUndefinedFromOptionalMembers-test.js index ab449e877b5a..e678880442b9 100644 --- a/scripts/js-api/build-types/transforms/typescript/__tests__/removeUndefinedFromOptionalMembers-test.js +++ b/scripts/js-api/build-types/transforms/typescript/__tests__/removeUndefinedFromOptionalMembers-test.js @@ -42,4 +42,20 @@ describe('removeUndefinedFromOptionalMembers', () => { };" `); }); + + test('should unwrap the lone remaining constituent, dropping redundant parens', async () => { + const code = ` + type Foo = { + a?: (() => void) | undefined, + b?: number | string | undefined, + }; + `; + const result = await translate(code); + expect(result).toMatchInlineSnapshot(` + "type Foo = { + a?: () => void; + b?: number | string; + };" + `); + }); }); diff --git a/scripts/js-api/build-types/transforms/typescript/ensureUndefinedOnOptionalMembers.js b/scripts/js-api/build-types/transforms/typescript/ensureUndefinedOnOptionalMembers.js new file mode 100644 index 000000000000..c1cf97ae2901 --- /dev/null +++ b/scripts/js-api/build-types/transforms/typescript/ensureUndefinedOnOptionalMembers.js @@ -0,0 +1,71 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type {PluginObj} from '@babel/core'; + +import * as t from '@babel/types'; + +/** + * Ensures optional object members carry an explicit `| undefined`, e.g. + * `foo?: number` becomes `foo?: number | undefined` (members that already + * include `undefined` are left unchanged). + * + * This is the format required by TypeScript consumers building with + * `exactOptionalPropertyTypes`, under which `foo?: T` and `foo?: T | undefined` + * are distinct. It applies to the per-module generated types; the API snapshot + * pipeline still strips it back via `removeUndefinedFromOptionalMembers`. + * + * This lives in React Native as a stopgap: flow-api-translator does not yet emit + * this format, and the generated types cannot wait for its next release. + * + * The API snapshot resets this via `removeUndefinedFromOptionalMembers`, which + * also unwraps the resulting single-constituent unions so function-valued + * members remain bare function types for `sortProperties` to group. + */ +const visitor: PluginObj = { + visitor: { + TSPropertySignature(path) { + if (path.node.optional !== true) { + return; + } + + const typeAnnotation = path.node.typeAnnotation; + if (!typeAnnotation || !t.isTSTypeAnnotation(typeAnnotation)) { + return; + } + + const actualTypeAnnotation = typeAnnotation.typeAnnotation; + + if (t.isTSUndefinedKeyword(actualTypeAnnotation)) { + return; + } + + if (t.isTSUnionType(actualTypeAnnotation)) { + if ( + actualTypeAnnotation.types.some(type => t.isTSUndefinedKeyword(type)) + ) { + return; + } + typeAnnotation.typeAnnotation = t.tsUnionType([ + ...actualTypeAnnotation.types, + t.tsUndefinedKeyword(), + ]); + return; + } + + typeAnnotation.typeAnnotation = t.tsUnionType([ + actualTypeAnnotation, + t.tsUndefinedKeyword(), + ]); + }, + }, +}; + +module.exports = visitor; diff --git a/scripts/js-api/build-types/transforms/typescript/removeUndefinedFromOptionalMembers.js b/scripts/js-api/build-types/transforms/typescript/removeUndefinedFromOptionalMembers.js index 195ec9262d85..d4318882cc18 100644 --- a/scripts/js-api/build-types/transforms/typescript/removeUndefinedFromOptionalMembers.js +++ b/scripts/js-api/build-types/transforms/typescript/removeUndefinedFromOptionalMembers.js @@ -29,11 +29,27 @@ const visitor: PluginObj = { return; } - const newTypeAnnotation = t.cloneDeep(actualTypeAnnotation); - newTypeAnnotation.types = newTypeAnnotation.types.filter( + const remainingTypes = actualTypeAnnotation.types.filter( type => t.isTSUndefinedKeyword(type) === false, ); - typeAnnotation.typeAnnotation = newTypeAnnotation; + if (remainingTypes.length === actualTypeAnnotation.types.length) { + return; + } + + // Unwrap to the bare type when a single constituent remains, otherwise a + // wrapper node survives that prints identically but breaks downstream + // transforms (e.g. `sortProperties`) that key on the node type. The lone + // constituent may be parenthesized (a function type inside a union needs + // parens, e.g. `(() => void) | undefined`); those parens are redundant + // once it is no longer part of a union. + if (remainingTypes.length === 1) { + const [remaining] = remainingTypes; + typeAnnotation.typeAnnotation = t.isTSParenthesizedType(remaining) + ? remaining.typeAnnotation + : remaining; + } else { + typeAnnotation.typeAnnotation = t.tsUnionType(remainingTypes); + } }, }, }; diff --git a/scripts/js-api/build-types/translateSourceFile.js b/scripts/js-api/build-types/translateSourceFile.js index 44bfc2e7f07a..952310db9062 100644 --- a/scripts/js-api/build-types/translateSourceFile.js +++ b/scripts/js-api/build-types/translateSourceFile.js @@ -30,6 +30,7 @@ const preTransforms: Array = [ ]; const postTransforms = (filePath: string): Array> => [ require('./transforms/typescript/convertTypeAliasesToInterfaces'), + require('./transforms/typescript/ensureUndefinedOnOptionalMembers'), require('./transforms/typescript/replaceProtectedConstructors'), require('./transforms/typescript/replaceDefaultExportName')(filePath), ];