Skip to content

StyleSheet.absoluteFillObject aliased to numeric absoluteFill style ID — breaks spreads (and types) #1200

@theonetheycallneo

Description

@theonetheycallneo

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions