StyleSheet.absoluteFillObject is aliased to the numeric absoluteFill style ID, breaking spreads on web
Summary
In react-native-unistyles@3.2.5, StyleSheet.absoluteFillObject is set to the registered style ID of absoluteFill — at both the type and runtime levels — instead of the actual style object. Code that spreads or merges with absoluteFillObject no longer compiles, and at runtime on web the value is a number, not an object.
This is a behavior change vs. React Native's own StyleSheet, which still exposes absoluteFillObject as a real {position:'absolute', top:0, left:0, right:0, bottom:0} object. Existing code that relied on the symmetry is broken.
Affected versions
Confirmed on react-native-unistyles@3.2.5. Earlier 3.x versions had the same alias on the runtime side; the type narrowing has been there at least since 3.2.4.
Reproduction
import { StyleSheet } from 'react-native-unistyles';
// TS2698: Spread types may only be created from object types.
const style = {
...StyleSheet.absoluteFillObject,
backgroundColor: 'red',
};
// Runtime (web): style is `<numeric id>`, not the absoluteFill descriptor.
console.log(StyleSheet.absoluteFillObject); // -> a number, e.g. 1
By contrast, React Native's own StyleSheet:
import { StyleSheet } from 'react-native';
console.log(StyleSheet.absoluteFillObject);
// { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }
Root cause
src/specs/StyleSheet/index.ts:
HybridUnistylesStyleSheet.absoluteFillObject = NativeStyleSheet.absoluteFill;
HybridUnistylesStyleSheet.absoluteFill = NativeStyleSheet.absoluteFill;
Both absoluteFill and absoluteFillObject are aliased to NativeStyleSheet.absoluteFill, but in upstream React Native (and React Native Web) those two are different things:
StyleSheet.absoluteFill — the registered style ID (a number on web, an internal identifier on native)
StyleSheet.absoluteFillObject — the actual style descriptor object
The type definitions reflect the same mistake:
src/specs/StyleSheet/index.d.ts:
export interface UnistylesStyleSheet extends UnistylesStyleSheetSpec {
absoluteFillObject: typeof NativeStyleSheetType.absoluteFill; // ← should be `.absoluteFillObject`
absoluteFill: typeof NativeStyleSheetType.absoluteFill;
...
}
Suggested fix
// Runtime
HybridUnistylesStyleSheet.absoluteFillObject = NativeStyleSheet.absoluteFillObject;
HybridUnistylesStyleSheet.absoluteFill = NativeStyleSheet.absoluteFill;
// Types
export interface UnistylesStyleSheet extends UnistylesStyleSheetSpec {
absoluteFillObject: typeof NativeStyleSheetType.absoluteFillObject;
absoluteFill: typeof NativeStyleSheetType.absoluteFill;
...
}
This restores parity with React Native's StyleSheet and unbreaks spread/merge usages.
Workaround we're using
// eslint-disable-next-line no-restricted-imports
import { StyleSheet as RNStyleSheet } from 'react-native';
import { StyleSheet } from 'react-native-unistyles';
const styles = StyleSheet.create((theme) => ({
backdrop: {
...RNStyleSheet.absoluteFillObject,
backgroundColor: theme.colors.backdrop,
},
}));
Importing react-native's StyleSheet only for absoluteFillObject and using unistyles' StyleSheet for create(). Not pretty (we have a lint rule banning react-native's StyleSheet import for the rest of the codebase), but it's the only correct value.
Environment
react-native-unistyles@3.2.5
- React Native Web 0.21.x (via Vite +
@storybook/react-native-web-vite)
- React Native 0.81.x
Related
- Likely same issue on native, but I only verified the web runtime value.
- Existing v2 codebases that used
...StyleSheet.absoluteFillObject will all need a workaround when upgrading to v3.
StyleSheet.absoluteFillObjectis aliased to the numericabsoluteFillstyle ID, breaking spreads on webSummary
In
react-native-unistyles@3.2.5,StyleSheet.absoluteFillObjectis set to the registered style ID ofabsoluteFill— at both the type and runtime levels — instead of the actual style object. Code that spreads or merges withabsoluteFillObjectno longer compiles, and at runtime on web the value is a number, not an object.This is a behavior change vs. React Native's own
StyleSheet, which still exposesabsoluteFillObjectas a real{position:'absolute', top:0, left:0, right:0, bottom:0}object. Existing code that relied on the symmetry is broken.Affected versions
Confirmed on
react-native-unistyles@3.2.5. Earlier 3.x versions had the same alias on the runtime side; the type narrowing has been there at least since 3.2.4.Reproduction
By contrast, React Native's own
StyleSheet:Root cause
src/specs/StyleSheet/index.ts:Both
absoluteFillandabsoluteFillObjectare aliased toNativeStyleSheet.absoluteFill, but in upstream React Native (and React Native Web) those two are different things:StyleSheet.absoluteFill— the registered style ID (a number on web, an internal identifier on native)StyleSheet.absoluteFillObject— the actual style descriptor objectThe type definitions reflect the same mistake:
src/specs/StyleSheet/index.d.ts:Suggested fix
This restores parity with React Native's
StyleSheetand unbreaks spread/merge usages.Workaround we're using
Importing
react-native'sStyleSheetonly forabsoluteFillObjectand using unistyles'StyleSheetforcreate(). Not pretty (we have a lint rule banningreact-native'sStyleSheetimport for the rest of the codebase), but it's the only correct value.Environment
react-native-unistyles@3.2.5@storybook/react-native-web-vite)Related
...StyleSheet.absoluteFillObjectwill all need a workaround when upgrading to v3.