Skip to content

Remove 'unspecified' from ColorSchemeName (#56686)#56686

Open
huntie wants to merge 1 commit intofacebook:mainfrom
huntie:export-D102527387
Open

Remove 'unspecified' from ColorSchemeName (#56686)#56686
huntie wants to merge 1 commit intofacebook:mainfrom
huntie:export-D102527387

Conversation

@huntie
Copy link
Copy Markdown
Member

@huntie huntie commented May 5, 2026

Summary:

Removes 'unspecified' from the return type of Appearance.getColorScheme() and useColorScheme(), splitting the setter input into a separate ColorSchemeOverride type. This resolves a longstanding misalignment between what native returns and what the types promise.

Motivation

'unspecified' is only meaningful as an input to setColorScheme() — neither iOS nor Android ever returns it from getColorScheme(). When setColorScheme('unspecified') is called, the JS layer re-queries the native module and caches the resolved system value.

After this change:

  • Appearance.getColorScheme() returns 'light' | 'dark' (no longer 'unspecified')
  • Appearance.setColorScheme() receives 'light' | 'dark' | 'unspecified'

Paired with docs updates:

History of this API

  • The TurboModule spec originally typed these methods as plain string because codegen didn't support union types (T52919652).
  • When support landed, D63681874 upgraded to ColorSchemeName = 'light' | 'dark' | 'unspecified' — a type-level cleanup that inadvertently widened return types to include 'unspecified', a value native never returns. This caused $FlowFixMe suppressions across downstream callers.
  • D80705652 later aligned the .d.ts and fixed a bug where setColorScheme('unspecified') threw an incorrect invariant.

Changelog:
[General][Breaking] - useColorScheme() no longer returns 'unspecified' (this was always the case, but is a breaking type change)

Reviewed By: cipolleschi

Differential Revision: D102527387

@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 5, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented May 5, 2026

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

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

@meta-codesync meta-codesync Bot changed the title Narrow ColorSchemeName, remove 'unspecified' from public API Narrow ColorSchemeName, remove 'unspecified' from public API (#56686) May 5, 2026
huntie added a commit to huntie/react-native that referenced this pull request May 5, 2026
…k#56686)

Summary:

Removes `'unspecified'` from the return type of `Appearance.getColorScheme()` and `useColorScheme()`, splitting the setter input into a separate `ColorSchemeOverride` type. This resolves a longstanding misalignment between what native returns and what the types promise.

**Motivation**

`'unspecified'` is only meaningful as an input to `setColorScheme()` — neither iOS nor Android ever returns it from `getColorScheme()`. When `setColorScheme('unspecified')` is called, the JS layer re-queries the native module and caches the resolved system value.

After this change:

- `Appearance.getColorScheme()` returns `'light' | 'dark'` (no longer `'unspecified'`)
- `Appearance.setColorScheme()` receives `'light' | 'dark' | 'unspecified'`

Paired with docs updates:
- facebook/react-native-website#5060
- facebook/react-native-website#5069

**History of this API**

- The TurboModule spec originally typed these methods as plain `string` because codegen didn't support union types (T52919652).
- When support landed, D63681874 upgraded to `ColorSchemeName = 'light' | 'dark' | 'unspecified'` — a type-level cleanup that inadvertently widened return types to include `'unspecified'`, a value native never returns. This caused `$FlowFixMe` suppressions across downstream callers.
- D80705652 later aligned the `.d.ts` and fixed a bug where `setColorScheme('unspecified')` threw an incorrect invariant.

Changelog:
[General][Breaking] - `useColorScheme()` no longer returns `'unspecified'` (this was always the case, but is a breaking type change)

Differential Revision: D102527387
@huntie huntie force-pushed the export-D102527387 branch from 0f6e19a to 476cfcf Compare May 5, 2026 17:16
@huntie huntie changed the title Narrow ColorSchemeName, remove 'unspecified' from public API (#56686) Remove 'unspecified' from ColorSchemeName (#56686) May 5, 2026
huntie added a commit to huntie/react-native that referenced this pull request May 6, 2026
Summary:

Removes `'unspecified'` from the return type of `Appearance.getColorScheme()` and `useColorScheme()`, splitting the setter input into a separate `ColorSchemeOverride` type. This resolves a longstanding misalignment between what native returns and what the types promise.

**Motivation**

`'unspecified'` is only meaningful as an input to `setColorScheme()` — neither iOS nor Android ever returns it from `getColorScheme()`. When `setColorScheme('unspecified')` is called, the JS layer re-queries the native module and caches the resolved system value.

After this change:

- `Appearance.getColorScheme()` returns `'light' | 'dark'` (no longer `'unspecified'`)
- `Appearance.setColorScheme()` receives `'light' | 'dark' | 'unspecified'`

Paired with docs updates:
- facebook/react-native-website#5060
- facebook/react-native-website#5069

**History of this API**

- The TurboModule spec originally typed these methods as plain `string` because codegen didn't support union types (T52919652).
- When support landed, D63681874 upgraded to `ColorSchemeName = 'light' | 'dark' | 'unspecified'` — a type-level cleanup that inadvertently widened return types to include `'unspecified'`, a value native never returns. This caused `$FlowFixMe` suppressions across downstream callers.
- D80705652 later aligned the `.d.ts` and fixed a bug where `setColorScheme('unspecified')` threw an incorrect invariant.

Changelog:
[General][Breaking] - `useColorScheme()` no longer returns `'unspecified'` (this was always the case, but is a breaking type change)

Differential Revision: D102527387
huntie added a commit to huntie/react-native that referenced this pull request May 6, 2026
Summary:

Removes `'unspecified'` from the return type of `Appearance.getColorScheme()` and `useColorScheme()`, splitting the setter input into a separate `ColorSchemeOverride` type. This resolves a longstanding misalignment between what native returns and what the types promise.

**Motivation**

`'unspecified'` is only meaningful as an input to `setColorScheme()` — neither iOS nor Android ever returns it from `getColorScheme()`. When `setColorScheme('unspecified')` is called, the JS layer re-queries the native module and caches the resolved system value.

After this change:

- `Appearance.getColorScheme()` returns `'light' | 'dark'` (no longer `'unspecified'`)
- `Appearance.setColorScheme()` receives `'light' | 'dark' | 'unspecified'`

Paired with docs updates:
- facebook/react-native-website#5060
- facebook/react-native-website#5069

**History of this API**

- The TurboModule spec originally typed these methods as plain `string` because codegen didn't support union types (T52919652).
- When support landed, D63681874 upgraded to `ColorSchemeName = 'light' | 'dark' | 'unspecified'` — a type-level cleanup that inadvertently widened return types to include `'unspecified'`, a value native never returns. This caused `$FlowFixMe` suppressions across downstream callers.
- D80705652 later aligned the `.d.ts` and fixed a bug where `setColorScheme('unspecified')` threw an incorrect invariant.

Changelog:
[General][Breaking] - `useColorScheme()` no longer returns `'unspecified'` (this was always the case, but is a breaking type change)

Reviewed By: cipolleschi

Differential Revision: D102527387
@huntie huntie force-pushed the export-D102527387 branch from 476cfcf to 4555464 Compare May 6, 2026 13:17
Summary:

Removes `'unspecified'` from the return type of `Appearance.getColorScheme()` and `useColorScheme()`, splitting the setter input into a separate `ColorSchemeOverride` type. This resolves a longstanding misalignment between what native returns and what the types promise.

**Motivation**

`'unspecified'` is only meaningful as an input to `setColorScheme()` — neither iOS nor Android ever returns it from `getColorScheme()`. When `setColorScheme('unspecified')` is called, the JS layer re-queries the native module and caches the resolved system value.

After this change:

- `Appearance.getColorScheme()` returns `'light' | 'dark'` (no longer `'unspecified'`)
- `Appearance.setColorScheme()` receives `'light' | 'dark' | 'unspecified'`

Paired with docs updates:
- facebook/react-native-website#5060
- facebook/react-native-website#5069

**History of this API**

- The TurboModule spec originally typed these methods as plain `string` because codegen didn't support union types (T52919652).
- When support landed, D63681874 upgraded to `ColorSchemeName = 'light' | 'dark' | 'unspecified'` — a type-level cleanup that inadvertently widened return types to include `'unspecified'`, a value native never returns. This caused `$FlowFixMe` suppressions across downstream callers.
- D80705652 later aligned the `.d.ts` and fixed a bug where `setColorScheme('unspecified')` threw an incorrect invariant.

Changelog:
[General][Breaking] - `useColorScheme()` no longer returns `'unspecified'` (this was always the case, but is a breaking type change)

Reviewed By: cipolleschi

Differential Revision: D102527387
@huntie huntie force-pushed the export-D102527387 branch from 4555464 to f9b8d1d Compare May 6, 2026 16:24
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