样式化组件 TypeScript
Styled Components TypeScript
使用 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,
})
更新: 经过进一步调查,在我弄清楚实际情况之前,@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 道具保持干净并通过 type-checks .
原答案:我不熟悉样式组件的语法(它看起来有点像 JSS,但不完全是)。
我建议使用标准语法。样式化的组件通常这样写:
const Container = styled.div`
user-select: none !important;
`;
它无法识别 !important
所以只需将它转换为任何安静的打字稿。
styled.div({
userSelect: 'none !important' as any
});
编辑 - 解释为何如此有效
很简单。如果你使用 ide 之类的原子,你可以 "go to" 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
不是一个选项,您必须将其转换为任何选项。
我刚刚在寻找稍微相关的内容时遇到了这个问题。我知道它已经解决了,但我已经使用样式化组件很长一段时间了,从来没有碰巧看到你提到的对象语法,我想这被包括在内是为了允许从其他 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};
`
快乐的样式组件
使用 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,
})
更新: 经过进一步调查,在我弄清楚实际情况之前,@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 道具保持干净并通过 type-checks .
原答案:我不熟悉样式组件的语法(它看起来有点像 JSS,但不完全是)。
我建议使用标准语法。样式化的组件通常这样写:
const Container = styled.div`
user-select: none !important;
`;
它无法识别 !important
所以只需将它转换为任何安静的打字稿。
styled.div({
userSelect: 'none !important' as any
});
编辑 - 解释为何如此有效
很简单。如果你使用 ide 之类的原子,你可以 "go to" 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
不是一个选项,您必须将其转换为任何选项。
我刚刚在寻找稍微相关的内容时遇到了这个问题。我知道它已经解决了,但我已经使用样式化组件很长一段时间了,从来没有碰巧看到你提到的对象语法,我想这被包括在内是为了允许从其他 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};
`
快乐的样式组件