我试图在我正在构建的样板项目中使用PayPal的Glamorous CSS-in-JS库,该项目还利用了TypeScript。

Glamorous允许您像这样添加道具到元​​素:

const Section = glamorous.section([
  {
    ...styles
  },
  ({size}: any){
    if(size === 'big') return {fontSize: '48px';}
    else if(size === 'small') return {fontSize: '12px';}
  },
  ({alignment}: any){
    if(alignment === 'left') return {textAlign: 'left'}
    else if(alignment === 'right') return {textAlign: 'right'}
  }
]);


这样您就可以像这样使用JSX中的元素:

<Section size="big"></Section>


我有很多这样的道具,我想将它们添加到我所有迷人的元素中。因此,我创建了一个如下所示的辅助函数:

export const special = (glam: any, styles: object[]): GBPComp =>{
  return glam([styles as CSSStyleDeclaration[], specialProps]);
};


其中specialProps表示一个函数(如上述函数),它将各种道具添加到我的样式声明数组中。

我打算这样使用它:

const Section = special(glamorous.section, [
  {
    ...styles
  }
]);


然后,我想输入specialProps提供的所有道具以用于我的JSX。因此,我试图创建我的GBPComp类型,如下所示:

export type GBPComp = React.StatelessComponent<CSSProperties&ExtraGlamorousProps&React.HTMLProps<HTMLElement>&{
  layout?: string,
  width?: string
}>;


问题在于并非所有返回的元素都必须具有React.HTMLProps<HTMLElement>属性。它们可能是HTMLAnchorElementHTMLTableElement等。

我如何能够动态生成我的GBPComp类型,从而将那些道具(即layoutwidth)添加到所有返回的类型中?这样,以下内容即可在TypeScript中正常工作:

const Section = special(glamorous.section, [
  {
    ...styles
  }
]);

const Anchor = special(glamorous.a, [
  {
    ...styles
  }
]);

<a href="#" layout="someString">This is an Anchor</a>

<section layout="someString">This is a Section</section>

最佳答案

如果不希望每个元素都使用React.HTMLProps<HTMLElement>,而不是对React.HTMLProps<HTMLElement>进行硬编码,则可以对GBPComp使用泛型,如下所示

export type GBPComp<ExtraProps> = React.StatelessComponent<React.CSSProperties & ExtraGlamorousProps & ExtraProps & {
  layout: string,
  width: string
}>;


并且special()也接受ExtraProps作为泛型,并像这样传递给GBPComp

export function special<ExtraProps>(glam: any, styles: object[], ...specialProps): GBPComp<ExtraProps> {
  return glam([styles as CSSStyleDeclaration[], ...specialProps]);
};


现在,您可以将React.HTMLProps<HTMLAnchorElement>道具分配给Anchor

const Anchor = special<React.HTMLProps<HTMLAnchorElement>>(glamorous.a, [
  {
    ...styles
  }
]);

10-06 00:41