包括对带有 typescript 的样式化组件主题的媒体查询

Posted

技术标签:

【中文标题】包括对带有 typescript 的样式化组件主题的媒体查询【英文标题】:including media queries to styled components theme with typescript 【发布时间】:2020-05-21 08:41:48 【问题描述】:

我正在使用带有 React 打字稿的样式化组件。我创建了一个 theme.ts,在其中定义了我在 ThemeProvider 中使用的变量,以将它们公开给我的应用程序。 此外,我有一个 styled.d.ts,我在其中声明了我的 DefaultTheme,我将其用作 theme.ts 的接口。

我创建了一个单独的文件。 media.ts 我在其中创建可重用的媒体查询,如本文所述:https://medium.com/@samuelresua/easy-media-queries-in-styled-components-690b78f50053, 现在我想在我的主题中包含 ...media 以便我可以将它与我的主题一起使用:

媒体.ts

import  css  from 'styled-components'

interface MediaQueryProps 
    [key: string]: any;
  
const breakpoints:  MediaQueryProps = 
   xs: 480,
   sm: 768,
   md: 992,
   lg: 1200 


export default Object.keys(breakpoints).reduce((acc, label) => 
   acc[label] = (literals: TemplateStringsArray, ...placeholders: any[]) => css`
      @media (max-width: $breakpoints[label]px) 
         $css(literals, ...placeholders);
      
   `.join("");
   return acc
,   as Record<keyof typeof breakpoints, (l: TemplateStringsArray, ...p: any[])=> string>)


主题.ts

import  DefaultTheme  from 'styled-components'
import media from './media';

const theme: DefaultTheme = 
    primary: "#262646",
    secondary: "#F9FAFE",
    success: "#00897B",
    danger: "#B00020",
    text: "#263646", 
    background: "#E8EAF6",
    white: "#ffffff",
    fonts: ["sans-serif", "Roboto"],
    ...media,
    fontSizes: 
      small: "1em",
      medium: "1.2em",
    ,
    
  export default theme;

styled.d.ts

// import original module declarations
import 'styled-components'

// and extend them!
declare module 'styled-components' 
  export interface DefaultTheme 
    primary: string,
    secondary: string,
    success: string,
    danger: string,
    text: string, 
    background: string,
    white: string,
    fonts: Array<string>,
    fontSizes: 
      small: string,
      medium: string,
    ,
  

如果我尝试在我的 App.ts 中使用我的媒体查询,而不在 DefaultTheme 中包含 ...media,则会引发错误 'DefaultTheme'.ts(2339)' 类型上不存在'属性'媒体',

const TableRow = styled.tr`
    &:nth-of-type(odd)
        background: $props => props.theme.secondary
    
    $(theme) => theme.media.sm`
        background: $theme.secondary
   `
`

但如果我将其定义为以下,则会引发错误

declare module 'styled-components' 
  export interface DefaultTheme 
    media: Array<string>
  
 

它在 theme.ts 中抛出错误 '主要:字符串;类型中缺少'属性'媒体'次要:字符串;成功:字符串;危险:字符串;文本:字符串;背景:字符串;白色:字符串;字体:字符串[];字体大小:小:字符串;介质:字符串; ; ' 但在类型 'DefaultTheme'.ts(2741)' 中是必需的

我完全不知道如何以正确的方式定义它以使其工作。 当我将鼠标悬停在媒体上时,我会收到以下信息表单打字稿:

(别名)常量媒体:记录字符串>

请帮助...

【问题讨论】:

【参考方案1】:

我认为您的问题是您定义了一个主题界面,其中没有定义从媒体导出的字段,但是您尝试在默认主题中使用它们,该类型是没有媒体字段的 Them .

最简单的方法是在您的界面中定义一个媒体字段,输入任何内容并将媒体查询放在媒体字段中。我不确定这是否适合您,或者这是否是一个好习惯。我在这种类型的主题方面工作不多,但我认为这样的事情应该可以完成。

【讨论】:

不确定这是否是您通过“在界面中定义媒体文件”所提到的,但我不得不从我的主题中删除 ...media,而是直接在主题,像这样:sm:media.sm,lg:media.lg,xs:media.xs,比我只能在我的界面中定义那些。所以删除传播运算符解决了我的问题 您正在创建一个theme,其类型为DefaultTheme(因此它没有扩展DefaultTheme)。这意味着您提供了额外的字段(通过在此行上发送媒体道具...media,。由于DefaultTheme 没有此类字段,它会引发错误。您的最后一个解决方案无效,原因有两个:首先...media不是返回媒体字段,而是返回其中的字段(如果您有const a = b:"B", c:"C" 而不是说const d = ...a,则d 对象将没有a 字段但将具有a (d == b:"B",c:"C") 的内容跨度> 您可以在此处阅读有关传播语法的更多信息:developer.mozilla.org/en-US/docs/Web/javascript/Reference/…。第二个解决方案是声明 2 个DefaultTheme 接口,这将导致冲突。

以上是关于包括对带有 typescript 的样式化组件主题的媒体查询的主要内容,如果未能解决你的问题,请参考以下文章

带有 Typescript 和样式化组件的 RN FlatList

带有 Typescript 和 ThemeProvider 的样式化组件。啥是正确的类型?

使用带有 typescript 的样式化组件“as”prop

使用带有Typescript的样式化组件,prop不存在?

如何在使用 TypeScript 的 create-react-app 中使用带有 babel 插件的样式化组件?

无法更改样式化组件主题提供程序