如何在TypeScript中动态扩展对象的接口或类型?

时间:2018-03-07 02:35:50

标签: javascript reactjs typescript jsx glamorous

我正在尝试在我正在构建的样板项目中使用PayPal的迷人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
  }
]);

然后,我希望为{JS}用法键入specialProps提供的所有道具。所以,我试图像这样创建我的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>

1 个答案:

答案 0 :(得分:1)

如果您不希望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
  }
]);