linaria icon indicating copy to clipboard operation
linaria copied to clipboard

feat: tightened typing for Object Interpolation (CSSProperties)

Open shqld opened this issue 5 years ago • 4 comments
trafficstars

Motivation

Object Interpolation is very useful especially for creating sass-like mixins such as

function margin(px: number): CSSProperties {
  return { margin: px + 'px' };
}

const divStyle = css`
  ${margin(12)}
`;

However, currently CSSProperties type accepts any keys and values even outside of CSS rule stuff. This is problematic for type safety and usability (e.g. auto-completion).

Summary

In this PR, I've just replaced declaration of CSSProperties.

Concretely, replaced [key: string]: string | number with csstype.Properties which is responsible for covering all available key-value pairs of css property.

This allows us more relialbe type cheking and usable auto-completion for Object Interpolation without downside in runtime.

For extendability of property types, internal interface called Properties is exported so that users can merge interface at their discretion in the user-land.

Test plan

function marginTop(px: number): CSSPropreties {
  return {
    // OK
    marginTop: px + 'px',
    // OK
    'margin-top': 0,
    // ERROR
    'margin-top': 1,
    // ERROR
    'my-prop': 'hello',
  };
}

css`
  ${{
    // OK
    marginTop: px + 'px',
    // OK
    'margin-top': 0,
    // ERROR
    'margin-top': 1,
    // ERROR
    'my-prop': 'hello',
  }}
`;
declare module 'linaria/lib/core/css' {
  interface Properties {
    'my-prop': 'hello';
  }
}

function marginTop(px: number): CSSPropreties {
  return {
    // OK
    'my-prop': 'hello',
  };
}

css`
  ${{
    // OK
    'my-prop': 'hello',
  }}
`;

shqld avatar Jul 29 '20 16:07 shqld

Hey @shqld, thank you for your pull request 🤗. The coverage report for this branch can be viewed here.

callstack-bot avatar Jul 29 '20 16:07 callstack-bot

Hi @shqld! Unfortunately, csstype doesn't work with CSS custom properties and it can be a problem for us. The problem looks unresolvable until that proposal isn't implemented.

Anber avatar Aug 10 '20 11:08 Anber

Hi @Anber !Thanks for your reply.

We can specify any types we want by overriding types using TypeScript's Declaration Merging (as I described above), so I believe it will still have some effect to do something like in this PR without special support for custom properties. At least no disadvantage is considered, IMHO.

shqld avatar Aug 18 '20 13:08 shqld

Hi @shqld! There is good news. TypeScript 4.1 introduces template literal types so that it will probably become possible to write the new CSSProperties type which can handle custom properties. Let's wait for the 4.1 release.

Anber avatar Oct 26 '20 08:10 Anber