Skip to content

Make generated props and style types augmentable - #58168

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

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
@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.

@zoontek

zoontek commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

@huntie @cortinico Do we have update on this PR review (and #58062)? Until then, a project with react-native-web and TS cannot really update to RN 0.87+

@cortinico

Copy link
Copy Markdown
Contributor

@huntie @cortinico Do we have update on this PR review (and #58062)?

I believe that #58062 has landed no?

@zoontek

zoontek commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor Author

@cortinico I don't think so, as reactwg/react-native-releases#1399 is still open and I see no trace of it in the changelogs. Also, with it alone (without this PR), ViewProps['style'], ImageProps['style'] and TextProps['style'] are reading ____ViewStyle_Internal and ____TextStyle_Internal, not the potentially extended ViewStyle and TextStyle.

EDIT: I confirm that it has landed in 0.88 latest RC, but that it doesn't fix everything and that this PR is still needed.

Screenshot 2026-09-17 at 12 41 15

@cortinico

Copy link
Copy Markdown
Contributor

@zoontek can you rebase and fix the conflict please?

Maher-Reven pushed a commit to Maher-Reven/expo that referenced this pull request Sep 25, 2026
Review feedback from @zoontek. Two of the removed members are ones where the
overlay was genuinely wider than React Native, rather than merely conflicting
with it:

- `position`, where React Native has 'absolute' | 'relative' | 'static' and the
  overlay added 'fixed' and 'sticky'.
- `cursor`, where React Native has CursorValue, 'auto' | 'pointer', against a
  much larger web set.

Both should come back once react/react-native#58168 makes the generated style
types augmentable, so leave them commented out with a TODO rather than dropping
them silently.

The other removals stay deletions, because React Native's own declaration is
already the wider one: `backgroundImage`, `backgroundSize`, `backgroundPosition`
and `backgroundRepeat` accept `ReadonlyArray<…> | string` against the overlay's
`string`, `boxShadow` and `filter` likewise, and `outlineColor` is
`____ColorValue_Internal`, which is `null | string | number | NativeColorValue`.
Restoring any of those would narrow the type again.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
zoontek and others added 3 commits September 25, 2026 17:04
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>
@zoontek
zoontek force-pushed the augmentable-props-and-styles branch from 25739b4 to 2eec85c Compare September 25, 2026 15:05
@zoontek

zoontek commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

@cortinico done ✅

@meta-codesync meta-codesync Bot closed this in 447ccd1 Sep 25, 2026
@meta-codesync meta-codesync Bot added the Merged This PR has been merged. label Sep 25, 2026
@meta-codesync

meta-codesync Bot commented Sep 25, 2026

Copy link
Copy Markdown

@cortinico merged this pull request in 447ccd1.

@zoontek
zoontek deleted the augmentable-props-and-styles branch September 25, 2026 23:33
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. Merged This PR has been merged. 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.

2 participants