Как динамически расширить интерфейс или тип объекта в TypeScript?
Я пытаюсь использовать библиотеку 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>
У меня есть несколько подобных вещей, которые я хотел бы добавить ко всем своим элементам, сгенерированным Glamorous. Итак, я создал вспомогательную функцию, которая выглядит следующим образом:
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>
, Они могут быть HTMLAnchorElement
или же HTMLTableElement
, так далее.
Как я могу быть в состоянии генерировать мой GBPComp
введите динмически, так что он добавляет эти реквизиты (т.е. layout
а также width
) всем возвращаемым типам? Так что следующее будет правильно работать в 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 ответ
Если вы не хотите 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
}
]);