Skip to content

Make generated props and style types augmentable - #58168

Open
zoontek wants to merge 3 commits into
react:mainfrom
zoontek:augmentable-props-and-styles
Open

Make generated props and style types augmentable#58168
zoontek wants to merge 3 commits into
react:mainfrom
zoontek:augmentable-props-and-styles

Conversation

@zoontek

@zoontek zoontek commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary:

react-native-web and Nativewind extend React Native's types with module augmentation. #58062 made the props and style types interfaces, which cleared the duplicate identifier errors. Two things still can't be extended.

Styles: ViewStyle is an interface derived from ____ViewStyle_Internal, but ViewProps['style'] reads the base, so augmenting ViewStyle doesn't reach it:

declare module 'react-native' {
  interface ViewStyle { transitionDuration?: string }
}

<View style={{ transitionDuration: '1s' }} />;             // error
StyleSheet.create({ box: { transitionDuration: '1s' } });  // error

____ViewStyle_Internal is now named ViewStyle, and the same for Text and Image. StyleSheet re-exports each name unchanged, so the interface and the base are one symbol.

Props written as inline object literals: The transform copies them into the interface body, where a second declaration is a merge conflict rather than an override, so the augmentation is silently ignored. Eleven of the 24 annotated types are affected. Each now moves its inline members into a private <Name>Core alias, so they reach the interface through the extends clause and are inherited, like everything from ViewProps already was:

// before
declare interface KeyboardAvoidingViewProps extends Readonly<ViewProps> {
  readonly enabled?: boolean
}

// after
declare interface KeyboardAvoidingViewProps extends Readonly<
  ViewProps & KeyboardAvoidingViewPropsCore
> {}

That costs 11 new names in the API snapshot, one per affected type. PressableProps set the precedent with PressableBaseProps.

ImagePropsBase and ImageBackgroundProps declare members that shadow keys of the type they spread, and a Flow spread of an optional property unions the two types instead of replacing the member, so those keys get an explicit Omit.

Caveat: an augmented member has to be assignable to the inherited one. Adding a key is clean and narrowing works, but widening raises TS2430 on the declaration file, which skipLibCheck: true silences.

Changelog:

[GENERAL] [CHANGED] - Allow module augmentation to extend generated props and style types

Test Plan:

yarn build-types: all 24 annotated types now emit an empty interface body. ViewStyle, TextStyle and ImageStyle are unchanged; the props types gain the 11 <Name>Core aliases.

Compiled augmentations with skipLibCheck: false. Styles: the two lines above pass here and report TS2353 on main. Props: adding a key and narrowing an existing one on each of the 11 types passes here and reports TS2717 on main.

yarn flow-check, yarn test-generated-typescript, yarn format-check and yarn lint: clean, apart from 3 Flow errors in packages/react-native-codegen/lib already on main. yarn jest packages/react-native/Libraries packages/react-native/src scripts/js-api: 632 tests pass, no snapshot changed.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 27, 2026
@github-actions

Copy link
Copy Markdown

Warning

JavaScript API change detected

This PR commits an update to ReactNativeApi.d.ts, indicating a change to React Native's public JavaScript API.

  • Please include a clear changelog message.
  • This change will be subject to additional review.

This change was flagged as: POTENTIALLY_BREAKING

@zoontek
zoontek force-pushed the augmentable-props-and-styles branch from db50e6b to 39ab067 Compare August 27, 2026 14:52
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Aug 27, 2026
zoontek and others added 2 commits August 27, 2026 17:02
Revert convertTypeAliasesToInterfaces to its original form. Get the same
emitted types from the Flow sources instead.

Styles: rename ____ViewStyle_Internal, ____TextStyle_Internal and
____ImageStyle_Internal to ViewStyle, TextStyle and ImageStyle.
StyleSheet now re-exports each name unchanged, with no alias.

Props: 11 annotated types still emitted members in the interface body.
Each one now moves its inline members into a private <Name>Core alias.
All members are inherited through the extends clause, so a module
augmentation can refine them.

ImagePropsBase and ImageBackgroundProps declare members that shadow keys
of the type they spread. An explicit Omit removes those keys, because a
Flow spread of an optional property unions the two types instead of
replacing the member.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@meta-codesync

meta-codesync Bot commented Aug 28, 2026

Copy link
Copy Markdown

@christophpurrer has imported this pull request. If you are a Meta employee, you can view this in D117876097.

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

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Expo Partner: Expo Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant