样式化的组件TypeScript

时间:2019-06-12 22:03:02

标签: javascript reactjs typescript styled-components

使用styled-components,在正常的React.js中,我可以这样做:

const Container = styled.div({
  userSelect: `none !important`,
})

但是使用TypeScript我会收到错误消息:

Argument of type '{ userSelect: string; }' is not assignable to parameter of type 'TemplateStringsArray'.
  Object literal may only specify known properties, and 'userSelect' does not exist in type 'TemplateStringsArray'.ts(2345)

解决此问题的最佳方法是什么?

我不想使用styled.div模板字符串方法,因为我发现它不太灵活。

例如,对于模板字符串,我们无法执行以下操作:

const flex = {
  flex: display: flex,
  col: flexDirection: `column`
}

const FlexRow = styled.div({
  ...flex.flex,
})

const FlexCol = styled.div({
   ...flex.flex,
   ...flex.col,
})

3 个答案:

答案 0 :(得分:5)

更新:在进一步调查中,在我弄清实际情况之前,@ Vincent似乎处在正确的轨道上。

import styled, { CSSObject } from "styled-components";

const Container = styled.div({
  userSelect: "none !important"
} as CSSObject);

会产生以下错误:

Conversion of type '{ userSelect: "none !important"; }' to type 'CSSObject' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Type '{ userSelect: "none !important"; }' is not comparable to type 'Properties<string | number>'.
    Types of property 'userSelect' are incompatible.
      Type '"none !important"' is not comparable to type '"contain" | "all" | "-moz-initial" | "inherit" | "initial" | "revert" | "unset" | "auto" | "none" | "text" | "-moz-none" | "element" | undefined'.ts(2352)

是的,即使在TypeScript中,样式化组件确实确实支持此语法,只是不理解后缀!important。这是您可能会稍作修改的解决方案:

const important = <T extends string>(s: T): T => `${s} !important` as T;

const Container = styled.div({
  userSelect: important("none"),
});

这有点笨拙(在显然不是的情况下,将"none !important"转换为"none"),但是它可以使样式CSS道具保持干净并通过类型检查。


原始答案:我对样式化组件的语法不熟悉(看起来有点像JSS,但不完全一样)。

我建议使用标准语法。样式化的组件通常是这样写的:

const Container = styled.div`
  user-select: none !important;
`;

答案 1 :(得分:4)

它无法识别!important,因此只需将其强制转换为任何文本即可安静打字稿。

styled.div({
  userSelect: 'none !important'  as any
});

编辑-为何可行

非常简单。如果您使用原子之类的想法,则可以“转到” userSelect属性的类型。类型为UserSelectProperty,其值必须是其中之一。

export type Globals = "-moz-initial" | "inherit" | "initial" | "revert" | "unset";
export type UserSelectProperty = Globals | "-moz-none" | "all" | "auto" | "contain" | "element" | "none" | "text";

由于none !important不是一个选项,因此您必须将其强制转换为任何一个。

答案 2 :(得分:0)

我只是在寻找稍微相关的问题时遇到了这个问题。我知道它已经解决了,但是我使用样式化组件已经有一段时间了,并且从未碰巧看到您所引用的对象语法,我认为它包含在内是为了允许其他css-in-js选项采用。

但是,我发表评论的原因是您的flex示例,使用带标签的模板文字可以达到非常相似的效果:

const flex = {
  flex: 'display: flex',
  col: 'flex-direction: column'
}

const FlexRow = styled.div`
  ${flex.flex};
`

const FlexCol = styled.div`
  ${flex.flex};
  ${flex.col};
`

快乐样式化组件