Skip to content

Extend emit-as-interface coverage for Uniwind compatibility#56811

Open
huntie wants to merge 3 commits into
facebook:mainfrom
huntie:export-D105028014
Open

Extend emit-as-interface coverage for Uniwind compatibility#56811
huntie wants to merge 3 commits into
facebook:mainfrom
huntie:export-D105028014

Conversation

@huntie
Copy link
Copy Markdown
Member

@huntie huntie commented May 13, 2026

Summary:
Extends the set of component props types annotated with build-types emit-as-interface to cover all types augmented by Uniwind.

This is a follow-up to D104808984, which added coverage for NativeWind and Expo. The additional types converted to interface declarations are:

  • ActivityIndicatorProps
  • ButtonProps
  • ImageBackgroundProps
  • KeyboardAvoidingViewProps
  • ModalBaseProps
  • PressableProps
  • RefreshControlProps
  • SectionListProps
  • TextInputProps
  • TextProps
  • TouchableHighlightProps

See https://github.com/uni-stack/uniwind/blob/a2406b8e04f5597b32a44febe01159c5223ee3c6/packages/uniwind/types.d.ts.

Changelog:
[General][Changed] - Strict TypeScript API: Additional component props types are now interface declarations, enabling module augmentation by libraries like Uniwind (preserve compatibility)

Differential Revision: D105028014

huntie added 3 commits May 13, 2026 10:28
Summary:

Adds a `--watch` flag to `yarn build-types`. Helpful when debugging output TS types end-to-end.

Changelog: [Internal]

Differential Revision: D104815967
…6809)

Summary:

#### Motivation

Adds (preserves) compatibility of Nativewind and Expo Web type augmentations with the Strict TypeScript API.

- These libraries rely on key React Native component types being defined as `interface`, not `type`, since TS module augmentation only supports `interface` declarations. 
- Previously, our opt-in generated TypeScript types (Strict TypeScript API) emitted all props types as `type Foo = Readonly<...>` ), matching Flow source. However, this API change vs our manual types (which predominantly used `interface` on props) breaks library compatibility in these cases.
- This is very awkward to otherwise solve in user space — so opt for backwards compatibility in our new types.

#### Primer

TypeScript module augmentation lets a library extend an existing module's types without modifying the source.

e.g. In Nativewind ([source](https://www.nativewind.dev/docs/guides/third-party-components)):

```ts
declare module 'react-native' {
  interface ScrollViewProps extends ViewProps, ScrollViewPropsIOS, ScrollViewPropsAndroid, Touchable {
    contentContainerClassName?: string;
    indicatorClassName?: string;
  }
  interface FlatListProps<ItemT> extends VirtualizedListProps<ItemT> {
    columnWrapperClassName?: string;
  }
  interface ViewProps {
    className?: string;
  }
}
```

Expo's `react-native-web.d.ts` ([source](https://unpkg.com/expo@54.0.31/types/react-native-web.d.ts)) also follows the same pattern across several component props types.

#### Changes

Add new `build-types` transform, implementing an opt-in `/** build-types emit-as-interface */` annotation, converting eligible `type` aliases to `interface` declarations.

- Changing the Flow source files directly isn't viable — Flow doesn't support `interface extends Omit<>`, and several of these types use `Omit<>` in their composition. The post-transform operates on the TypeScript output where `interface extends Readonly<Omit<...>>` is valid.

The following emitted types are updated:

| Type | Augmented by | Source |
|---|---|---|
| `ViewProps` | `className?` | [Nativewind](https://www.nativewind.dev/docs/guides/third-party-components), [Expo](https://unpkg.com/expo@54.0.31/types/react-native-web.d.ts) |
| `ScrollViewProps` | `contentContainerClassName?`, `indicatorClassName?` | [Nativewind](https://www.nativewind.dev/docs/guides/third-party-components) |
| `ImagePropsBase` | `className?` | [Expo](https://unpkg.com/expo@54.0.31/types/react-native-web.d.ts) |
| `SwitchProps` | `className?` | [Expo](https://unpkg.com/expo@54.0.31/types/react-native-web.d.ts) |
| `TouchableWithoutFeedbackProps` | `className?` | [Expo](https://unpkg.com/expo@54.0.31/types/react-native-web.d.ts) |
| `InputAccessoryViewProps` | `className?` | [Expo](https://unpkg.com/expo@54.0.31/types/react-native-web.d.ts) |

`FlatListProps` is not included in this PR: its bare intersection (no `Readonly<>` wrapper) has a conflicting `fadingEdgeLength` property across constituent types that cannot be expressed as a single `extends` clause without hitting TS2320. This will be addressed in a follow-up.

`VirtualizedListWithoutRenderItemProps<T>` in `react-native/virtualized-lists` is separately owned and not changed here.

Changelog:
[General][Changed] - **Strict TypeScript API**: Select component props types are now `interface` declarations, enabling module augmentation by libraries like NativeWind and Expo (preserve compatibility)

Differential Revision: D104808984
Summary:
Extends the set of component props types annotated with `build-types emit-as-interface` to cover all types augmented by Uniwind.

This is a follow-up to D104808984, which added coverage for NativeWind and Expo. The additional types converted to `interface` declarations are:

* `ActivityIndicatorProps`
* `ButtonProps`
* `ImageBackgroundProps`
* `KeyboardAvoidingViewProps`
* `ModalBaseProps`
* `PressableProps`
* `RefreshControlProps`
* `SectionListProps`
* `TextInputProps`
* `TextProps`
* `TouchableHighlightProps`

See https://github.com/uni-stack/uniwind/blob/a2406b8e04f5597b32a44febe01159c5223ee3c6/packages/uniwind/types.d.ts.

Changelog:
[General][Changed] - **Strict TypeScript API**: Additional component props types are now `interface` declarations, enabling module augmentation by libraries like Uniwind (preserve compatibility)

Differential Revision: D105028014
@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 May 13, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented May 13, 2026

@huntie has exported this pull request. If you are a Meta employee, you can view the originating Diff in D105028014.

@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

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. fb-exported meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant