Skip to content

Commit 27c45bd

Browse files
chore(types): enable exactOptionalPropertyTypes
Add `| undefined` to optional properties in type declarations and fabric native component specs to support TypeScript's exactOptionalPropertyTypes flag. This ensures downstream projects using this flag get no type errors from react-native-screens. Zero runtime changes — all modifications are type annotations only.
1 parent af0e6af commit 27c45bd

10 files changed

Lines changed: 107 additions & 69 deletions

src/components/safe-area/SafeAreaView.types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export type Edge = 'top' | 'right' | 'bottom' | 'left';
88
export type InsetType = 'all' | 'system' | 'interface';
99

1010
export interface SafeAreaViewProps extends ViewProps {
11-
edges?: Readonly<Partial<Record<Edge, boolean>>>;
11+
edges?: Readonly<Partial<Record<Edge, boolean>>> | undefined;
1212
// Android-only
1313
insetType?: InsetType;
1414
}

src/components/tabs/TabsScreen.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -280,17 +280,17 @@ function parseIconsToNativeProps(
280280
icon: PlatformIcon | undefined,
281281
selectedIcon: PlatformIcon | undefined,
282282
): {
283-
imageIconResource?: ImageResolvedAssetSource;
284-
drawableIconResourceName?: string;
285-
iconType?: IconType;
286-
iconImageSource?: ImageSourcePropType;
287-
iconResourceName?: string;
283+
imageIconResource?: ImageResolvedAssetSource | undefined;
284+
drawableIconResourceName?: string | undefined;
285+
iconType?: IconType | undefined;
286+
iconImageSource?: ImageSourcePropType | undefined;
287+
iconResourceName?: string | undefined;
288288
// android
289-
selectedImageIconResource?: ImageSourcePropType;
290-
selectedDrawableIconResourceName?: string;
289+
selectedImageIconResource?: ImageSourcePropType | undefined;
290+
selectedDrawableIconResourceName?: string | undefined;
291291
// iOS
292-
selectedIconImageSource?: ImageSourcePropType;
293-
selectedIconResourceName?: string;
292+
selectedIconImageSource?: ImageSourcePropType | undefined;
293+
selectedIconResourceName?: string | undefined;
294294
} {
295295
if (Platform.OS === 'android') {
296296
const { imageIconResource, drawableIconResourceName } =

src/fabric/ModalScreenNativeComponent.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,25 @@ type ReplaceAnimation = 'pop' | 'push';
6262
type OptionalBoolean = 'undefined' | 'false' | 'true';
6363

6464
export interface NativeProps extends ViewProps {
65-
onAppear?: CT.DirectEventHandler<ScreenEvent>;
66-
onDisappear?: CT.DirectEventHandler<ScreenEvent>;
67-
onDismissed?: CT.DirectEventHandler<ScreenDismissedEvent>;
68-
onNativeDismissCancelled?: CT.DirectEventHandler<ScreenDismissedEvent>;
69-
onWillAppear?: CT.DirectEventHandler<ScreenEvent>;
70-
onWillDisappear?: CT.DirectEventHandler<ScreenEvent>;
71-
onHeaderHeightChange?: CT.DirectEventHandler<HeaderHeightChangeEvent>;
72-
onTransitionProgress?: CT.DirectEventHandler<TransitionProgressEvent>;
73-
onGestureCancel?: CT.DirectEventHandler<ScreenEvent>;
74-
onHeaderBackButtonClicked?: CT.DirectEventHandler<ScreenEvent>;
75-
onSheetDetentChanged?: CT.DirectEventHandler<SheetDetentChangedEvent>;
65+
onAppear?: CT.DirectEventHandler<ScreenEvent> | undefined;
66+
onDisappear?: CT.DirectEventHandler<ScreenEvent> | undefined;
67+
onDismissed?: CT.DirectEventHandler<ScreenDismissedEvent> | undefined;
68+
onNativeDismissCancelled?:
69+
| CT.DirectEventHandler<ScreenDismissedEvent>
70+
| undefined;
71+
onWillAppear?: CT.DirectEventHandler<ScreenEvent> | undefined;
72+
onWillDisappear?: CT.DirectEventHandler<ScreenEvent> | undefined;
73+
onHeaderHeightChange?:
74+
| CT.DirectEventHandler<HeaderHeightChangeEvent>
75+
| undefined;
76+
onTransitionProgress?:
77+
| CT.DirectEventHandler<TransitionProgressEvent>
78+
| undefined;
79+
onGestureCancel?: CT.DirectEventHandler<ScreenEvent> | undefined;
80+
onHeaderBackButtonClicked?: CT.DirectEventHandler<ScreenEvent> | undefined;
81+
onSheetDetentChanged?:
82+
| CT.DirectEventHandler<SheetDetentChangedEvent>
83+
| undefined;
7684
screenId?: CT.WithDefault<string, ''>;
7785
sheetAllowedDetents?: number[];
7886
sheetLargestUndimmedDetent?: CT.WithDefault<CT.Int32, -1>;

src/fabric/ScreenNativeComponent.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,25 @@ type ScrollEdgeEffect = 'automatic' | 'hard' | 'soft' | 'hidden';
6464
type OptionalBoolean = 'undefined' | 'false' | 'true';
6565

6666
export interface NativeProps extends ViewProps {
67-
onAppear?: CT.DirectEventHandler<ScreenEvent>;
68-
onDisappear?: CT.DirectEventHandler<ScreenEvent>;
69-
onDismissed?: CT.DirectEventHandler<ScreenDismissedEvent>;
70-
onNativeDismissCancelled?: CT.DirectEventHandler<ScreenDismissedEvent>;
71-
onWillAppear?: CT.DirectEventHandler<ScreenEvent>;
72-
onWillDisappear?: CT.DirectEventHandler<ScreenEvent>;
73-
onHeaderHeightChange?: CT.DirectEventHandler<HeaderHeightChangeEvent>;
74-
onTransitionProgress?: CT.DirectEventHandler<TransitionProgressEvent>;
75-
onGestureCancel?: CT.DirectEventHandler<ScreenEvent>;
76-
onHeaderBackButtonClicked?: CT.DirectEventHandler<ScreenEvent>;
77-
onSheetDetentChanged?: CT.DirectEventHandler<SheetDetentChangedEvent>;
67+
onAppear?: CT.DirectEventHandler<ScreenEvent> | undefined;
68+
onDisappear?: CT.DirectEventHandler<ScreenEvent> | undefined;
69+
onDismissed?: CT.DirectEventHandler<ScreenDismissedEvent> | undefined;
70+
onNativeDismissCancelled?:
71+
| CT.DirectEventHandler<ScreenDismissedEvent>
72+
| undefined;
73+
onWillAppear?: CT.DirectEventHandler<ScreenEvent> | undefined;
74+
onWillDisappear?: CT.DirectEventHandler<ScreenEvent> | undefined;
75+
onHeaderHeightChange?:
76+
| CT.DirectEventHandler<HeaderHeightChangeEvent>
77+
| undefined;
78+
onTransitionProgress?:
79+
| CT.DirectEventHandler<TransitionProgressEvent>
80+
| undefined;
81+
onGestureCancel?: CT.DirectEventHandler<ScreenEvent> | undefined;
82+
onHeaderBackButtonClicked?: CT.DirectEventHandler<ScreenEvent> | undefined;
83+
onSheetDetentChanged?:
84+
| CT.DirectEventHandler<SheetDetentChangedEvent>
85+
| undefined;
7886
screenId?: CT.WithDefault<string, ''>;
7987
sheetAllowedDetents?: number[];
8088
sheetLargestUndimmedDetent?: CT.WithDefault<CT.Int32, -1>;

src/fabric/ScreenStackHeaderConfigNativeComponent.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,20 @@ export interface NativeProps extends ViewProps {
7272
blurEffect?: CT.WithDefault<BlurEffect, 'none'>;
7373
// TODO: implement this props on iOS
7474
topInsetEnabled?: boolean;
75-
headerLeftBarButtonItems?: CT.UnsafeMixed[];
76-
headerRightBarButtonItems?: CT.UnsafeMixed[];
77-
onPressHeaderBarButtonItem?: CT.DirectEventHandler<OnPressHeaderBarButtonItemEvent>;
78-
onPressHeaderBarButtonMenuItem?: CT.DirectEventHandler<OnPressHeaderBarButtonMenuItemEvent>;
75+
headerLeftBarButtonItems?: CT.UnsafeMixed[] | undefined;
76+
headerRightBarButtonItems?: CT.UnsafeMixed[] | undefined;
77+
onPressHeaderBarButtonItem?:
78+
| CT.DirectEventHandler<OnPressHeaderBarButtonItemEvent>
79+
| undefined;
80+
onPressHeaderBarButtonMenuItem?:
81+
| CT.DirectEventHandler<OnPressHeaderBarButtonMenuItemEvent>
82+
| undefined;
7983
synchronousShadowStateUpdatesEnabled?: CT.WithDefault<boolean, false>;
8084

8185
// Experimental
82-
userInterfaceStyle?: CT.WithDefault<UserInterfaceStyle, 'unspecified'>;
86+
userInterfaceStyle?:
87+
| CT.WithDefault<UserInterfaceStyle, 'unspecified'>
88+
| undefined;
8389
}
8490

8591
export default codegenNativeComponent<NativeProps>(

src/fabric/ScreenStackNativeComponent.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ type FinishTransitioningEvent = Readonly<{}>;
99
export interface NativeProps extends ViewProps {
1010
iosPreventReattachmentOfDismissedScreens?: CT.WithDefault<boolean, true>;
1111

12-
onFinishTransitioning?: CT.DirectEventHandler<FinishTransitioningEvent>;
12+
onFinishTransitioning?:
13+
| CT.DirectEventHandler<FinishTransitioningEvent>
14+
| undefined;
1315
}
1416

1517
export default codegenNativeComponent<NativeProps>('RNSScreenStack', {});

src/fabric/safe-area/SafeAreaViewNativeComponent.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import type { CodegenTypes as CT, ViewProps } from 'react-native';
77
type InsetType = 'all' | 'system' | 'interface';
88

99
export interface NativeProps extends ViewProps {
10-
edges?: Readonly<{
11-
top: boolean;
12-
right: boolean;
13-
bottom: boolean;
14-
left: boolean;
15-
}>;
10+
edges?:
11+
| Readonly<{
12+
top: boolean;
13+
right: boolean;
14+
bottom: boolean;
15+
left: boolean;
16+
}>
17+
| undefined;
1618
// Android-only
1719
insetType?: CT.WithDefault<InsetType, 'all'>;
1820
}

src/fabric/tabs/TabsScreenNativeComponent.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,33 @@ type LifecycleStateChangeEvent = Readonly<{
2323
}>;
2424

2525
export type ItemStateAppearance = {
26-
tabBarItemTitleFontFamily?: string;
27-
tabBarItemTitleFontSize?: CT.Float;
28-
tabBarItemTitleFontWeight?: string;
29-
tabBarItemTitleFontStyle?: string;
30-
tabBarItemTitleFontColor?: ProcessedColorValue | null;
26+
tabBarItemTitleFontFamily?: string | undefined;
27+
tabBarItemTitleFontSize?: CT.Float | undefined;
28+
tabBarItemTitleFontWeight?: string | undefined;
29+
tabBarItemTitleFontStyle?: string | undefined;
30+
tabBarItemTitleFontColor?: ProcessedColorValue | null | undefined;
3131
tabBarItemTitlePositionAdjustment?: {
3232
horizontal?: CT.Float;
3333
vertical?: CT.Float;
3434
};
35-
tabBarItemIconColor?: ProcessedColorValue | null;
36-
tabBarItemBadgeBackgroundColor?: ProcessedColorValue | null;
35+
tabBarItemIconColor?: ProcessedColorValue | null | undefined;
36+
tabBarItemBadgeBackgroundColor?: ProcessedColorValue | null | undefined;
3737
};
3838

3939
export type ItemAppearance = {
40-
normal?: ItemStateAppearance;
41-
selected?: ItemStateAppearance;
42-
focused?: ItemStateAppearance;
43-
disabled?: ItemStateAppearance;
40+
normal?: ItemStateAppearance | undefined;
41+
selected?: ItemStateAppearance | undefined;
42+
focused?: ItemStateAppearance | undefined;
43+
disabled?: ItemStateAppearance | undefined;
4444
};
4545

4646
export type Appearance = {
47-
stacked?: ItemAppearance;
48-
inline?: ItemAppearance;
49-
compactInline?: ItemAppearance;
47+
stacked?: ItemAppearance | undefined;
48+
inline?: ItemAppearance | undefined;
49+
compactInline?: ItemAppearance | undefined;
5050

51-
tabBarBackgroundColor?: ProcessedColorValue | null;
52-
tabBarShadowColor?: ProcessedColorValue | null;
51+
tabBarBackgroundColor?: ProcessedColorValue | null | undefined;
52+
tabBarShadowColor?: ProcessedColorValue | null | undefined;
5353
tabBarBlurEffect?: CT.WithDefault<BlurEffect, 'systemDefault'>;
5454
};
5555

src/types.tsx

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,16 @@ export interface PlatformIcon {
149149

150150
export interface ScreenProps extends ViewProps {
151151
active?: 0 | 1 | Animated.AnimatedInterpolation<number>;
152-
activityState?: 0 | 1 | 2 | Animated.AnimatedInterpolation<number>;
152+
activityState?:
153+
| 0
154+
| 1
155+
| 2
156+
| Animated.AnimatedInterpolation<number>
157+
| undefined;
153158
/**
154159
* Boolean indicating that the screen should be frozen with `react-freeze`.
155160
*/
156-
shouldFreeze?: boolean;
161+
shouldFreeze?: boolean | undefined;
157162
children?: React.ReactNode;
158163
/**
159164
* Boolean indicating that swipe dismissal should trigger animation provided by `stackAnimation`. Defaults to `false`.
@@ -309,9 +314,9 @@ export interface ScreenProps extends ViewProps {
309314
/**
310315
* A callback that gets called when the header height has changed.
311316
*/
312-
onHeaderHeightChange?: (
313-
e: NativeSyntheticEvent<HeaderHeightChangeEventType>,
314-
) => void;
317+
onHeaderHeightChange?:
318+
| ((e: NativeSyntheticEvent<HeaderHeightChangeEventType>) => void)
319+
| undefined;
315320
/**
316321
* A callback that gets called after swipe back is canceled.
317322
*/
@@ -414,7 +419,13 @@ export interface ScreenProps extends ViewProps {
414419
*
415420
* Defaults to `[1.0]`.
416421
*/
417-
sheetAllowedDetents?: number[] | 'fitToContents' | 'medium' | 'large' | 'all';
422+
sheetAllowedDetents?:
423+
| number[]
424+
| 'fitToContents'
425+
| 'medium'
426+
| 'large'
427+
| 'all'
428+
| undefined;
418429
/**
419430
* Integer value describing elevation of the sheet, impacting shadow on the top edge of the sheet.
420431
*
@@ -1306,9 +1317,9 @@ export type ScreensRefsHolder = Record<string, React.RefObject<View>>;
13061317

13071318
export interface GestureProps {
13081319
screensRefs?: React.MutableRefObject<ScreensRefsHolder>;
1309-
currentScreenId?: string;
1310-
goBackGesture?: GoBackGesture;
1311-
transitionAnimation?: AnimatedScreenTransition;
1320+
currentScreenId?: string | undefined;
1321+
goBackGesture?: GoBackGesture | undefined;
1322+
transitionAnimation?: AnimatedScreenTransition | undefined;
13121323
screenEdgeGesture?: boolean;
13131324
}
13141325

tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"resolveJsonModule": true,
2121
"skipLibCheck": true,
2222
"strict": true,
23+
"exactOptionalPropertyTypes": true,
2324
"target": "esnext",
2425
"types": ["jest", "node"]
2526
},

0 commit comments

Comments
 (0)