Describe the issue
defineConsts values are resolved to CSS var() references by the babel plugin when accessed inside stylex.create(). This means JavaScript arithmetic operators on defineConsts values silently produce wrong results — the + operator performs string concatenation on var() strings instead of numeric addition.
TypeScript does not catch this because defineConsts preserves the input types in its return type (StyleX$DefineConsts returns DefaultTokens), so numeric constants are typed as number even though they're strings at compile time.
Expected behavior
defineConsts values should behave as their literal values inside stylex.create(). Arithmetic like Constants.A + Constants.B where both are numeric constants should produce the correct numeric result (e.g., 26 + 14 = 40), not string concatenation ("var(--A-hash)var(--B-hash)").
Outside stylex.create(), the babel plugin correctly inlines defineConsts values as numeric literals, so arithmetic works there. The behavior should be consistent.
Steps to reproduce
@stylexjs/babel-plugin v0.18.2, @stylexjs/stylex v0.18.2
- Define numeric constants in a
.stylex.ts file:
// constants.stylex.ts
import * as stylex from "@stylexjs/stylex";
export const C = stylex.defineConsts({
A: 26,
B: 14,
D: 6,
});
- Use arithmetic on those constants inside
stylex.create() in another file:
// component.tsx
import * as stylex from "@stylexjs/stylex";
import { C } from "./constants.stylex";
const styles = stylex.create({
box: { height: C.A + C.B - C.D }, // Expected: 34px, Actual: NaN or wrong value
});
- The build succeeds with no errors, but the generated CSS has an incorrect
height value.
Test case
The root cause is in evaluateThemeRef in the babel plugin. Both defineVars and defineConsts imports from .stylex files are routed through the same 'themeNameRef' codepath in importPathResolver, which returns a Proxy that resolves every property access to a var(--name) string:
// babel-plugin/lib/index.js — evaluateThemeRef (around line 5846)
function evaluateThemeRef(fileName, exportName, state) {
const resolveKey = key => {
// ...hashing...
return `var(--${varName})`; // Always returns a string
};
const proxy = new Proxy({}, {
get(_, key) {
return resolveKey(key); // C.A becomes "var(--A-hash)"
},
});
return proxy;
}
Then in the BinaryExpression evaluator (around line 6247):
case '+':
return left + right; // "var(--A-hash)" + "var(--B-hash)" = string concatenation
Template literal interpolation (`${C.A}px`) works because String("var(--A-hash)") is valid and the post-processor resolves it. But arithmetic on two var() strings is nonsense.
Additional comments
No response
Describe the issue
defineConstsvalues are resolved to CSSvar()references by the babel plugin when accessed insidestylex.create(). This means JavaScript arithmetic operators ondefineConstsvalues silently produce wrong results — the+operator performs string concatenation onvar()strings instead of numeric addition.TypeScript does not catch this because
defineConstspreserves the input types in its return type (StyleX$DefineConstsreturnsDefaultTokens), so numeric constants are typed asnumbereven though they're strings at compile time.Expected behavior
defineConstsvalues should behave as their literal values insidestylex.create(). Arithmetic likeConstants.A + Constants.Bwhere both are numeric constants should produce the correct numeric result (e.g.,26 + 14 = 40), not string concatenation ("var(--A-hash)var(--B-hash)").Outside
stylex.create(), the babel plugin correctly inlinesdefineConstsvalues as numeric literals, so arithmetic works there. The behavior should be consistent.Steps to reproduce
@stylexjs/babel-pluginv0.18.2,@stylexjs/stylexv0.18.2.stylex.tsfile:stylex.create()in another file:heightvalue.Test case
The root cause is in
evaluateThemeRefin the babel plugin. BothdefineVarsanddefineConstsimports from.stylexfiles are routed through the same'themeNameRef'codepath inimportPathResolver, which returns a Proxy that resolves every property access to avar(--name)string:Then in the BinaryExpression evaluator (around line 6247):
Template literal interpolation (
`${C.A}px`) works becauseString("var(--A-hash)")is valid and the post-processor resolves it. But arithmetic on twovar()strings is nonsense.Additional comments
No response