Skip to content

fix(web): take the variable name the native variable hooks take - #496

Open
YevheniiKotyrlo wants to merge 6 commits into
nativewind:mainfrom
YevheniiKotyrlo:fix/web-variable-hook-parameters
Open

YevheniiKotyrlo wants to merge 6 commits into
nativewind:mainfrom
YevheniiKotyrlo:fix/web-variable-hook-parameters

Conversation

@YevheniiKotyrlo

@YevheniiKotyrlo YevheniiKotyrlo commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Problem

TypeScript resolves the root entry to the web plane, so its declarations are the ones every consumer type-checks against. useNativeVariable and useUnstableNativeVariable take no arguments there, while native takes the variable name, so useNativeVariable("--color"), written for native, fails with TS2554: Expected 0 arguments, but got 1.

Solution

Both web hooks take the name native takes, and still throw, as web reads no variable through them.

Tests

src/__tests__/_web-native-api-parity.types.ts holds every function both planes export to the same parameters, and fails yarn typecheck while any two differ. On #423 it fails for the two hooks; on main it also fails for vars() and <VariableContextProvider />, which #423 aligns.

Verification

On Ubuntu with the workflow's steps - build, lint, typecheck, yarn test, node --test node/__tests__/*.mjs, both library builds, the web export, the unstaged-changes checks and commitlint - everything passes.

Merge order

Stacked on #423, without which the parity test fails for vars() and <VariableContextProvider />, so #423 lands first. #423 carries #431, so the order is #431, #423, then this.

vars() and <VariableContextProvider /> mapped every entry of the record
they are given into the runtime's variable record, so an entry whose value
is undefined planted a key holding undefined. Variable lookup is
presence-keyed, so that key read as "set to nothing" and stopped the cascade
before the inherited value, the :root value and the var() fallback.

Both channels now build the record through toVariableRecord, which strips
the -- prefix and skips an entry with no value, the invariant the compiler
already holds. "unset" remains how a variable is deliberately cleared.
…nour

vars() and VariableContextProvider were typed Record<string, string | number>
on web and Record<string, StyleDescriptor> on native, and a consumer only
sees the web declarations, since the root entry's types re-export ./web. A
font-family list or an undefined entry was a type error though native takes
both, while StyleDescriptor admits var() tuples and null that web cannot
serialise: web's vars() threw on undefined and null, and its provider passed
raw values into the style.

CustomPropertyValue is the set both platforms honour: a string, a number, a
boolean, undefined, or an array of those, which is a comma-separated list.
Both platforms type vars() and VariableContextProvider with it, and web
serialises through one function that leaves an undefined value unset. A
type-level fixture holds the three entries to one type, and the README shows
the provider by its current name.
TypeScript resolves the root entry to the web plane, so its signatures
are the ones every consumer type-checks against. `useNativeVariable`
and `useUnstableNativeVariable` took no arguments there, and a call
written for native failed to type-check.

A type test holds every function both planes export to the same
parameters.
@YevheniiKotyrlo
YevheniiKotyrlo marked this pull request as ready for review October 16, 2026 15:02
The case compiled with the default options, so the compiler inlined the
class's --color into the rule reading it and the result never depended
on how the runtime treats an undefined entry. It now keeps the
variable, so the class's value reaches the element only because an
undefined entry plants no key, and writes the colour as a hex with no
name, so both paths serialise it alike.
@YevheniiKotyrlo
YevheniiKotyrlo marked this pull request as draft October 16, 2026 17:50
@YevheniiKotyrlo
YevheniiKotyrlo marked this pull request as ready for review October 16, 2026 18:14

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant