【问题标题】:Typescript and CSS-modules typesTypescript 和 CSS 模块类型
【发布时间】:2019-03-05 00:10:12
【问题描述】:

我不想对 CSS 模块使用愚蠢的 mock,而是使用真正的类型,所以我使用 webpack 插件typings-for-css-modules-loader

对于简单的 css

.foo { color: red; }
.bar { color: green; }

可以生成example.css.d.ts声明

export interface ILocals {
  'foo': string;
  'bar': string;
}
export interface IExampleCss {
  locals: ILocals;
  'foo': string;
  'bar': string;
}

declare const styles: IExampleCss

export default styles;

所以在我的代码中我可以像这样使用它

import css from './example.css';

const { locals } = css;

<div className={locals.foo}>Red</div>
<div className={css.bar}>Green</div>

而且 VSCode 知道 locals.foo 和 css.bar 成员

我尝试编写一个函数,它能够在 typescript 中获取任何 css 定义作为输入参数

interface IStringHash {
    [key: string]: string;
}
interface ICSSLocals {
    locals: IStringHash;
    [key: string]: string | IStringHash;
}

interface ISomeInterface {
    renderComponent: (css: ICSSLocals): React.ReactNode
}

const myFunction = (css: IExampleCss) => {
    return (
        <div key="1" className={css.locals.foo}>Red</div>
        <div key="2" className={css.bar}>Green</div>
    )
}

const MyRenderer: ISomeInterface = {
    renderComponent: myFunction
                     ^^^^^^^^^^
};

我得到错误:

[ts] Type 'IExampleCss' is not assignable to type 'ICSSLocals'. Type 'IExampleCss' is not assignable to type 'ICSSLocals'. Types of property 'locals' are incompatible. Type 'ILocals' is not assignable to type 'IStringHash'. Index signature is missing in type 'ILocals'.

怎么了?

我在typescript playground写了一个相关的示例

// Declaration with generics
interface IStringHash {
    [key: string]: string;
}
interface ICSSModule {
    locals: IStringHash;
    [key: string]: string | IStringHash;
}

interface returnObject {
    a: string,
    b: string
}

interface ISomeInterface {
    renderComponent: (css: ICSSModule) => returnObject
}

// usage with certain realisation
export interface ILocals {
  'foo': string;
  'bar': string;
}
export interface IExampleCss {
  locals: ILocals;
  'foo': string;
  'bar': string;
}

const myFunction = (css: IExampleCss): returnObject => {
    return {
        a: css.locals.foo,
        b: css.bar
    }
}

const MyRenderer: ISomeInterface = {
    renderComponent: myFunction
      ^^^^^^^
};

这是错误:

[ts] Type '(css: IExampleCss) => returnObject' is not assignable to type '(css: ICSSModule) => returnObject'. Types of parameters 'css' and 'css' are incompatible. Type 'ICSSModule' is not assignable to type 'IExampleCss'. Property ''foo'' is missing in type 'ICSSModule'. (property) ISomeInterface.renderComponent: (css: ICSSModule) => returnObject

【问题讨论】:

  • 您能否提供更多信息,您在使用myFunction 做什么?采用“任何 CSS 声明”似乎并不比仅使用 any 类型好多少。
  • @Ski 我已经修复了上面的功能
  • @Ski 我需要类型建议,如果有显示错误
  • 我很困惑:如果myFunction 访问css.locals.foocss.bar,那么它只适用于类名为foobar 的CSS 模块。那么,你为什么要声明 myFunction 采用任何 CSS 模块?
  • @MattMcCutchen 我为服务器和浏览器的使用风格使用了一些加载器——所以它并不那么重要

标签: typescript css-modules


【解决方案1】:

好的做法是只需要你需要的界面而不是更多。所以看起来bar 不应该在ILocalsfoo 不应该在IExampleCss

export interface ILocals {
  'foo': string;   
//  'bar': string; <--
}
export interface IExampleCss {
  locals: ILocals;
  // 'foo': string; <--
  'bar': string;
}

const myFunction = (css: IExampleCss): returnObject => {
    return {
        a: css.locals.foo,
        b: css.bar
    }
}

旁注:对于简单的情况,您不必声明返回类型——它会被推断出来。而如果需要函数返回值的类型,可以使用ReturnType&lt;myFunction&gt;

【讨论】:

  • css.locals.foo 用于示例显示任何项目都可以直接访问或通过locals 访问
  • 抱歉搞混了,foo 应该留下,bar 应该离开
猜你喜欢
  • 2019-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-06
  • 2016-05-14
  • 1970-01-01
  • 2016-06-23
  • 2017-12-07
相关资源
最近更新 更多