typescript - 在 styled-components 中为 css 函数指定类型
我正在按照文档中的示例创建媒体模板,但在输入要传递给 css 函数的参数(示例中的纯 JS 版本)时遇到了很大困难:
const sizes = {
desktop: 992
}
const media = Object.keys(sizes).reduce((acc, label) => {
acc[label] = (...args) => css` // <----- how to type args
@media(max-width: ${sizes[label]}px) {
${css(...args)}
}
`
return acc
}, {})
如果你了解 TS 但不了解 styled-components,args 是一个标签模板字面量,所以我会这样使用 media 对象:
media.desktop`
background-color: blue;
${variable}
`
我尝试将 args 类型定义为 TemplateStringsArray,但 TS 报错,因为展开参数需要是 array 类型(我认为它是,但 somehow 它未被识别)。如果我将类型改为 TemplateStringsArray[],css() 函数会报错,因为它至少需要 1 个参数,但收到的是 0 个或更多。
答案#1
标记模板的签名应该是 (literals: TemplateStringsArray, ...placeholders: any[]) => string,其中 literals 是模板中的字符串,placeholders 是变量的值。
如果你只是想将所有参数传递给 css,你可以使用 call。Typescript 不会让你直接展开参数,因为 css 有必需的参数,ts 编译器会尝试检查这些参数:
acc[label] = (...args: any[]) => css`
@media(max-width: ${sizes[label]}px) {
${css.call(undefined, ...args)}
}
`
一个完全类型化的版本,能正确地为 media.* 函数指定类型,将是:
const sizes = {
desktop: 992
}
const media = Object.keys(sizes).reduce((acc, label) => {
acc[label] = (literals: TemplateStringsArray, ...placeholders: any[]) => css`
@media(max-width: ${sizes[label]}px) {
${css(literals, ...placeholders)}
}
`;
return acc
}, {} as Record<keyof typeof sizes, (l: TemplateStringsArray, ...p: any[]) => string>)
答案#2
Titian Cernicova-Dragomir 的解决方案很棒,但对我不起作用。它会生成带有逗号的字符串。所以我在 css 函数中添加了 join。
import { css } from "styled-components";
const sizes = {
desktop: 730,
};
const media = Object.keys(sizes).reduce(
(acc, label) => {
acc[label] = (literals: TemplateStringsArray, ...placeholders: any[]) =>
css`
@media (max-width: ${sizes[label]}px) {
${css(literals, ...placeholders)};
}
`.join("");
return acc;
},
{} as Record<
keyof typeof sizes,
(l: TemplateStringsArray, ...p: any[]) => string
>,
);
export default media;
