atlassian-labs / compiled

A familiar and performant compile time CSS-in-JS library for React.
https://compiledcssinjs.com
Apache License 2.0
1.98k stars 68 forks source link

CSS Map has its output property types unexpectedly expanded at times #1639

Closed itsdouges closed 6 months ago

itsdouges commented 6 months ago

Describe the bug

Sometimes properties on the output object are expanded to string unexpectedly. This affects passing values to XCSS prop that expect narrowed types.

To Reproduce

import { cssMap } from '@compiled/react';

const stylesValidRoot = cssMap({
  primary: {
    color: 'var(--ds-text)',
    '&:hover': { color: 'var(--ds-text-hover)', background: 'var(--ds-surface-hover)' },
  },
});

stylesValidRoot.primary.['&:hover'].background // string

However if we define it as backgroundColor it stays narrowed:

import { cssMap } from '@compiled/react';

const stylesValidRoot = cssMap({
  primary: {
    color: 'var(--ds-text)',
    '&:hover': { color: 'var(--ds-text-hover)', backgroundColor: 'var(--ds-surface-hover)' },
  },
});

stylesValidRoot.primary.['&:hover'].backgroundColor // 'var(--ds-surface-hover)'

Expected behavior

The property remains narrowed to 'var(--ds-surface-hover)'.

Additional context

This was found during the strict typing refactor, see:

https://github.com/atlassian-labs/compiled/pull/1636/files#diff-1d4b97255cb11e9b25307047d51c7f2c1d94052d4626cc8e19c410a8b0444788R299

kylorhall-atlassian commented 6 months ago

This bug goes away when removing the generic from CSS.Properties, fixing in https://github.com/atlassian-labs/compiled/pull/1640

export default function cssMap<
-  TStyles extends Record<string, CSS.Properties<number | string> & WhitelistedSelector & ExtendedSelectors>
+  TStyles extends Record<string, CSS.Properties & WhitelistedSelector & ExtendedSelectors>
+  TStyles extends Record<string, CSS.Properties<(string & {}) | 0> & WhitelistedSelector & ExtendedSelectors> // default
+  TStyles extends Record<string, CSS.Properties<(string & {}) | number> & WhitelistedSelector & ExtendedSelectors> // what we should use?
>(

Can't tell you why, not sure I really understand what TLength is doing in the csstype package.

However, I can't find a way to infer the number, even CSS.Properties<(string & {}) | (number & {})> doesn't work:

Screenshot 2024-03-07 at 10 35 16 AM