React多泛型条件Typography组件类型定义问题求助
实现灵活的React Typography组件问题
我正在React中实现一个Typography组件,需要满足以下灵活需求:
variant属性为必填项as属性为可选项:- 若
as为字符串(代表原生HTML标签),需暴露该标签的对应属性 - 若
as为React元素,需暴露该React元素的属性 - 若未定义
as,则默认使用variant映射的元素
- 若
举个例子:当as="a"时,组件应支持href属性。
我编写了如下示例代码,单独测试Proxy类型时功能正常,但将其应用到React组件中时无法正常工作:
import React from "react"; const TypographyDefaultMapping = { h1: 'h1', h2: 'h2', h3: 'h3', 'body-medium': 'span', label: 'span', } as const; export type TypographyVariants = keyof typeof TypographyDefaultMapping; type Tags = keyof HTMLElementTagNameMap; type AsType = undefined | Tags | React.FunctionComponent<any>; type VariantsDefaultType<T extends TypographyVariants> = Omit< React.ComponentPropsWithoutRef<typeof TypographyDefaultMapping[T]>, 'as' > & { variant: TypographyVariants; }; export type NewConditionalTypography< T extends AsType, V extends TypographyVariants > = T extends undefined ? VariantsDefaultType<V> // Undefined "as" property, fallback to variant's default : T extends Tags ? { variant: TypographyVariants; as: Tags; bloup: boolean; } & React.ComponentPropsWithoutRef<T> // "as" property is a valid HTML tag : T extends React.FunctionComponent<any> // "as" property is a React element ? { variant: TypographyVariants; as: React.FunctionComponent<any>; bib: boolean; } & React.ComponentProps<T> : never; type Proxy<T = unknown> = T extends { as: infer As extends AsType; variant: infer Var extends TypographyVariants; } ? NewConditionalTypography<As, Var> : T extends { variant: infer Var extends TypographyVariants; // case of not defined "as" } ? NewConditionalTypography<undefined, Var> : never; const NewTypography = (props: Proxy) => ( <div>Test: {JSON.stringify(props)}</div> ); const Link = ({ linkClick }: { linkClick: () => void }) => ( <button onClick={linkClick}>Test</button> ); // Expected to get HTMLHeadingElement props + variant prop type TestProxy = Proxy<{ variant: 'h2' }>; // ^? // Expected to get HTMLSpanElement props + variant prop type TestProxySpan = Proxy<{ variant: 'body-medium' }>; // ^? // Expected to get HTMLAnchor props + variant prop type TestProxy2 = Proxy<{ variant: 'h2'; as: 'a' }>; // ^? // Expected to get Link element props + variant prop type TestProxy3 = Proxy<{ variant: 'h2'; as: typeof Link }>; // ^? const TestingComponent = () => ( <div> // Should allow (and auto-complete) "href" <NewTypography variant="h2" /> // Should allow (and auto-complete) "linkClick" <NewTypography variant="body-medium" as={Link} // linkClick={() => console.log('Test')} /> // Should not allow "href" <NewTypography variant="body-medium" as="span" href="www.example.com" /> </div> );
请问如何实现该需求,且该方案是否具备可行性?
内容的提问来源于stack exchange,提问作者konsalex
相关产品推荐
相关产品推荐

