【问题标题】:How to define css variables in style attribute in React and typescript如何在 React 和 typescript 的 style 属性中定义 css 变量
【发布时间】:2019-01-30 23:18:51
【问题描述】:

我想这样定义 jsx:

<table style={{'--length': array.lenght}}>
   <tbody>
      <tr>{array}</tr>
   </tbody>
</table>

我在 CSS 中使用 --length,我也有单元格有 --count 使用 CSS 伪选择器(使用计数器 hack)显示计数。

但是打字稿会抛出错误:

TS2326: Types of property 'style' are incompatible.
  Type '{ '--length': number; }' is not assignable to type 'CSSProperties'.
    Object literal may only specify known properties, and ''--length'' does not exist in type 'CSSProperties'.

是否可以更改样式属性的类型以接受 CSS 变量(自定义属性),或者有没有办法强制任何样式对象?

【问题讨论】:

  • 为什么要css变量?因为您不能在样式标签中使用 CSS 变量。它只接受 CSS 属性。你可以创建一个像 const length = array.length 这样的变量并在 css 中使用 length
  • 我相信这里讨论过github.com/facebook/react/issues/6411
  • @SGhaleb 我已经看到了这一点,在我的代码中,css 变量有效,它们出现在 DOM 中并且应用了 css,但是在构建应用程序时它们在 webpack 中给出错误(看起来像错误但编译通过) ,所以这是打字稿打字的问题而不是反应。
  • @KyawSiesein 他们对 js 变量的问题是你不能在 ::before::after 中使用它们。

标签: reactjs typescript jsx tsx


【解决方案1】:

如果你去definition of CSSProperties,你会看到:

export interface CSSProperties extends CSS.Properties<string | number> {
    /**
     * The index signature was removed to enable closed typing for style
     * using CSSType. You're able to use type assertion or module augmentation
     * to add properties or an index signature of your own.
     *
     * For examples and more information, visit:
     * https://github.com/frenic/csstype#what-should-i-do-when-i-get-type-errors
     */
}

该链接提供了如何通过在csstype 中扩充Properties 的定义或将属性名称转换为any 来解决类型错误的示例。

【讨论】:

  • 谢谢,看起来正是我想要的,将在星期一的工作中尝试这个,正在尝试使用 react 样板,但它不是最新的,它给了我开箱即用的错误。
  • 刚刚测试了第二个例子,看起来更简单,也很有效。
  • 链接已过期,如果它在可能指向提交而不是 master 之前有用。
【解决方案2】:

像这样:

render(){
  var style = { "--my-css-var": 10 } as React.CSSProperties;
  return <div style={style}>...</div>
}

【讨论】:

  • 我认为这是我在接受答案的示例之后得到的结果,但直接回答总是更好。
  • @ixrock 非常感谢!
【解决方案3】:

您可以向变量添加类型断言。 {['--css-variable' as any]: value }

<table style={{['--length' as any]: array.lenght}}>
   <tbody>
      <tr>{array}</tr>
   </tbody>
</table>

【讨论】:

  • 谢谢,也许会记得何时最终测试这个,我现在无法测试这个,我没有任何 React 项目。
  • 抑制打字稿错误不是最好的解决方案
【解决方案4】:

style 转换为any 违背了使用TypeScript 的全部目的,因此我建议使用您的自定义属性集扩展React.CSSProperties

import React, {CSSProperties} from 'react';

export interface MyCustomCSS extends CSSProperties {
  '--length': number;
}

通过扩展 React.CSSProperties,您将保持 TypeScript 的属性检查有效,并且您将被允许使用您的自定义 --length 属性。

使用MyCustomCSS 将如下所示:

const MyComponent: React.FC = (): JSX.Element => {
  return (
    <input
      style={
        {
          '--length': 300,
        } as MyCustomCSS
      }
    />
  );
};

【讨论】:

  • 这很有趣,因为现在样式只能有特定的自定义属性。不知道其他答案如何处理这个问题,我也没有任何反应/打字稿项目要测试。
  • @jcubic 因为MyCustomCSS 扩展自CSSProperties 其他属性也应该是可分配的。
  • 我的意思是我喜欢这个解决方案,因为我只能使用我在类型中定义的自定义属性,所以如果我设置 --length: number; 这将是我唯一可以使用的自定义属性。我知道 css 的其余部分工作正常,这就是 extend 对任何语言的工作方式。 “只能有特定的自定义属性”是指对于 CSS 中的所有自定义属性,只有那些由类型定义的属性才有效。
  • TS 4.4 支持模板文字类型,因此可以编写类似这样的内容,而不是显式指定所有自定义变量:[key: `--${string}`]: string | number;。一个班轮:type MyCustomCSS = CSSProperties &amp; Record&lt;`--${string}`, number | string&gt;;
  • 我更喜欢这一种衬垫解决方案 (@brc-dd) 我已经测试过,我确认它可以完美运行!
【解决方案5】:
import "react";

type CustomProp = { [key in `--${string}`]: string };
declare module "react" {
  export interface CSSProperties extends CustomProp {}
}

把它放在你的 global.d.ts 文件中

【讨论】:

  • 它比现有答案好在哪里?
  • 我认为覆盖 react typescript 类型不是一个好主意。所以我会说这是kludge 的典型示例。
  • @jcubic React 开发人员不同意你的观点,stackoverflow.com/a/52013197/247482中引用的评论证明了这一点
  • @flyingsheep 这不是覆盖类型,它只是显示代码的样子。
  • @flyingsheep 也许我应该给你这个问题的实际解决方案。它没有覆盖内置类型。
【解决方案6】:

您可以简单地将这个模块声明合并使用字符串模板放在文件顶部或任何 .d.ts 文件中,然后您将能够使用任何以“--”开头的 CSS 变量,即字符串或数字

declare module 'react' {
    interface CSSProperties {
        [key: `--${string}`]: string | number
    }
}

例如

<div style={{ "--value": percentage }} />

【讨论】:

  • 所以你建议覆盖内置类型,如果你有10个模块并且每个模块使用不同的变量怎么办?
  • 你可能知道 typescript 接口默认是合并的,它们不会覆盖现有的,而是扩展它们,来源:typescriptlang.org/docs/handbook/declaration-merging.html
  • 我最终使用了这个解决方案,谢谢。需要注意的一件事:可以传入带有多于两个破折号的值(因为破折号是一个字符串)。例如,这很好:style={{ ---color: 'red' }}。这对我的用例来说不是问题,但如果其他人也有同样的疑问,我只是想将其添加为注释。
  • 是的,您可以使用任何有效的 javascript 字符串作为 typescript 模板文字字符串中的模式
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-27
  • 2021-06-03
  • 2017-11-30
相关资源
最近更新 更多