使用 TypeScript 键入的样式系统道具

Posted

技术标签:

【中文标题】使用 TypeScript 键入的样式系统道具【英文标题】:styled-system props typing with TypeScript 【发布时间】:2019-05-11 16:40:23 【问题描述】:

我正在使用styled-system,库的一个关键是使用速记道具来轻松快速地进行主题化。

我已经简化了我的组件,但有趣的是:

import React from 'react'
import styled from 'styled-components'
import  color, ColorProps  from 'styled-system'

const StyledDiv = styled('div')<ColorProps>`
  $color
`

const Text = ( color : ColorProps) => 
  return <StyledDiv color=color />

我在 color 道具上有一个错误,上面写着:

键入'字符串 | (字符串 | 空)[] | undefined' 不可分配给 输入'字符串 | (字符串 & (字符串 | null)[]) |未定义'。

我认为这是因为 styled-system 使用与原生 html 属性 color 相同的命名,并且会发生冲突。

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

不要使用ColorProps,而是尝试使用color: CSS.ColorProperty(`import * as CSS from 'csstype');这是一个要点,展示了我如何使用 typescript/styled-system 创建一些类型化的“Box”原语:https://gist.github.com/chiplay/d10435c0962ec62906319e12790104d1

祝你好运!

【讨论】:

这不是选择不使用 styled-system 的响应数组值作为颜色属性的能力吗?【参考方案2】:

color 似乎在 HTMLAttributes 下的 react 声明文件中声明 - 它没有被导出。

我必须通过创建 custom prop 来解决这个问题

示例使用@emotion/styled,但也适用于styled-components

// component.js
import styled from '@emotion/styled';
import  style, ResponsiveValue  from 'styled-system';
import CSS from 'csstype';

const textColor = style(
  prop: 'textColor',
  cssProperty: 'color',
  key: 'colors'
);


type Props = 
  textColor?: ResponsiveValue<CSS.ColorProperty>


const Box = styled.div<Props>`
  $textColor;
`

export default Box;
// some-implementation.js
import Box from '.';

const Page = () => (
  <Box textColor=['red', 'green']>Content in a box</Box>
);

【讨论】:

【参考方案3】:

我所做的是使用 Typescript 转换功能并保持样式系统逻辑完整。例如:

const Heading: React.FC<ColorProps> = ( color, children ) => 
  return <HeadingContainer color=(color as any) ...props>children</HeadingContainer>;
;

【讨论】:

【参考方案4】:

以 Chris 的回答为基础,并使用 custom props 上的最新文档。

// core/constants/theme.ts
// Your globally configured theme file
export const theme =  colors:  primary: ['#0A43D2', '#04122B']  

// core/constants/styledSystem.ts
import 
  color as ssColor,
  ColorProps as SSColorProps,
  TextColorProps,
  compose,
  system,
 from 'styled-system'

// Styled-system patch for the color prop fixing "Types of property 'color' are incompatible"
// when appling props to component that extend ColorProps.
export interface ColorProps extends Omit<SSColorProps, 'color'> 
  textColor?: TextColorProps['color']


export const color = compose(
  ssColor,
  system(
    // Alias color as textColor
    textColor: 
      property: 'color',
      // This connects the property to your theme, so you can use the syntax shown below E.g "primary.0".
      scale: 'colors'
    
  )
)

// components/MyStyledComponent.ts
import  color, ColorProps  from 'core/constants/styledSystem.ts'

interface MyStyledComponentProps extends ColorProps 

export const MyStyledComponent = styled.div<MyStyledComponentProps>`
  $color
`

// components/MyComponent.ts
export const MyComponent = () => <MyStyledComponent textColor="primary.0">...

编辑:更新到 styled-components ^5.0.0 修复了这个问题

https://github.com/styled-components/styled-components/blob/master/CHANGELOG.md#v500---2020-01-13

【讨论】:

【参考方案5】:

只是添加到 xuanlopez' 的答案 - 不确定 5.0.0 版本具体解决了什么问题 - 但使用 $color 作为重命名的道具而不是 textColor 将其指定为样式组件中的 transient prop 所以作为道具,它不会出现在渲染的 DOM 中。

【讨论】:

以上是关于使用 TypeScript 键入的样式系统道具的主要内容,如果未能解决你的问题,请参考以下文章

样式化组件 + Typescript:如何键入 css 辅助函数?

如何在 Vue3 中启用仅使用 TypeScript 的道具键入

如何在 Typescript 中使用道具在情感/样式样式组件之间共享样式

不能使用带有情感 js 和 typescript 的样式组件的道具

如何使用 Material UI 和 TypeScript 将自定义道具传递给样式化组件?

样式化的 MUI 无法在 typescript 中将组件道具传递给 Typography