linaria
linaria copied to clipboard
feat: tightened typing for Object Interpolation (CSSProperties)
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',
}}
`;
Hey @shqld, thank you for your pull request 🤗. The coverage report for this branch can be viewed here.
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.
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.
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.