Skip to content

Commit 9539ddb

Browse files
committed
Align legacy TypeScript ImageStyle with ViewStyle
The hand-written `ImageStyle` interface in `types_DEPRECATED` redeclared a small subset of `ViewStyle` properties instead of extending it, so newer style props such as `filter`, `boxShadow`, `mixBlendMode`, `outlineColor` and `pointerEvents` were rejected on `<Image>` styles. Both other sources of truth already include them: the Flow `____ImageStyle_InternalCore` spreads `$Exact<____ViewStyle_Internal>`, and the generated strict API declares `Omit<____ViewStyle_Internal, 'overflow'>`. Extend `ViewStyle` with `overflow` omitted, mirroring the strict API, so `overflow` stays narrowed to 'visible' | 'hidden' on images.
1 parent 551d12a commit 9539ddb

2 files changed

Lines changed: 85 additions & 11 deletions

File tree

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @format
8+
*/
9+
10+
import * as React from 'react';
11+
// @ts-ignore
12+
import {Image, StyleSheet, type ImageStyle} from 'react-native';
13+
14+
// `ImageStyle` must accept every `ViewStyle` property. This matches the Flow
15+
// definition of `____ImageStyle_InternalCore`, which spreads
16+
// `____ViewStyle_Internal`, and the generated strict API, which declares
17+
// `Omit<____ViewStyle_Internal, 'overflow'> & {...}`.
18+
const viewStyleProperties: ImageStyle = {
19+
backgroundImage: 'linear-gradient(to right, red, blue)',
20+
borderCurve: 'continuous',
21+
boxShadow: '0 0 10px red',
22+
cursor: 'pointer',
23+
elevation: 4,
24+
filter: 'brightness(0.5)',
25+
isolation: 'isolate',
26+
mixBlendMode: 'multiply',
27+
outlineColor: 'red',
28+
outlineOffset: 2,
29+
outlineStyle: 'dashed',
30+
outlineWidth: 1,
31+
pointerEvents: 'none',
32+
};
33+
34+
// Image-specific properties remain available.
35+
const imageStyleProperties: ImageStyle = {
36+
objectFit: 'contain',
37+
overlayColor: 'red',
38+
resizeMode: 'cover',
39+
tintColor: 'blue',
40+
};
41+
42+
// Unlike `ViewStyle`, `overflow` on `ImageStyle` is narrowed to
43+
// 'visible' | 'hidden' — 'scroll' is not accepted.
44+
const overflowVisible: ImageStyle = {overflow: 'visible'};
45+
const overflowHidden: ImageStyle = {overflow: 'hidden'};
46+
// @ts-expect-error - 'scroll' is not a valid `overflow` value for `ImageStyle`
47+
const overflowScroll: ImageStyle = {overflow: 'scroll'};
48+
49+
// Unknown properties are still rejected.
50+
// @ts-expect-error - 'notAStyleProperty' does not exist on `ImageStyle`
51+
const unknownProperty: ImageStyle = {notAStyleProperty: 1};
52+
53+
const styles = StyleSheet.create({
54+
image: {
55+
boxShadow: '0 0 10px red',
56+
filter: 'brightness(0.5)',
57+
resizeMode: 'cover',
58+
} as ImageStyle,
59+
});
60+
61+
export function App() {
62+
return (
63+
<>
64+
<Image
65+
source={{uri: 'https://reactnative.dev/img/logo-og.png'}}
66+
style={styles.image}
67+
/>
68+
{/* The user-visible path: writing `ViewStyle` properties inline on `<Image>`. */}
69+
<Image
70+
source={{uri: 'https://reactnative.dev/img/logo-og.png'}}
71+
style={{filter: 'brightness(0.5)', mixBlendMode: 'multiply'}}
72+
/>
73+
</>
74+
);
75+
}
76+
77+
export {
78+
imageStyleProperties,
79+
overflowHidden,
80+
overflowScroll,
81+
overflowVisible,
82+
unknownProperty,
83+
viewStyleProperties,
84+
};

packages/react-native/types_DEPRECATED/Libraries/StyleSheet/StyleSheetTypes.d.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -638,20 +638,10 @@ export interface TextStyle extends TextStyleIOS, TextStyleAndroid, ViewStyle {
638638
* Image style
639639
* @see https://reactnative.dev/docs/image#style
640640
*/
641-
export interface ImageStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle {
641+
export interface ImageStyle extends Omit<ViewStyle, 'overflow'> {
642642
resizeMode?: ImageResizeMode | undefined;
643-
backfaceVisibility?: 'visible' | 'hidden' | undefined;
644-
borderBottomLeftRadius?: AnimatableNumericValue | string | undefined;
645-
borderBottomRightRadius?: AnimatableNumericValue | string | undefined;
646-
backgroundColor?: ColorValue | undefined;
647-
borderColor?: ColorValue | undefined;
648-
borderRadius?: AnimatableNumericValue | string | undefined;
649-
borderTopLeftRadius?: AnimatableNumericValue | string | undefined;
650-
borderTopRightRadius?: AnimatableNumericValue | string | undefined;
651643
overflow?: 'visible' | 'hidden' | undefined;
652644
overlayColor?: ColorValue | undefined;
653645
tintColor?: ColorValue | undefined;
654-
opacity?: AnimatableNumericValue | undefined;
655646
objectFit?: 'cover' | 'contain' | 'fill' | 'scale-down' | 'none' | undefined;
656-
cursor?: CursorValue | undefined;
657647
}

0 commit comments

Comments
 (0)