[英]Using props.children and styled-component "as" prop with typescript
I've looked through several existing solutions and posts and couldn't really find any solution.我浏览了几个现有的解决方案和帖子,但实际上找不到任何解决方案。
So, I'm using React with Typescript and styled-component.因此,我将 React 与 Typescript 和样式组件一起使用。
One part of my project is the Heading
component.我的项目的一部分是
Heading
组件。 Ideally, I imagined to used it like <Heading level={2}>Hello world!</Heading>
wherever I need it.理想情况下,我想像
<Heading level={2}>Hello world!</Heading>
一样在需要的地方使用它。
Here is the simplified Codesandbox Code of it 这是它的简化 Codesandbox 代码
However, the <S.Heading
throws Errors in my Linter, even though it seems to work visually speaking.然而,
<S.Heading
在我的 Linter 中抛出了错误,尽管它似乎在视觉上起作用。
Error错误
This JSX tag's 'children' prop expects type 'never' which requires multiple children, but only a single child was provided.ts(2745)
这个 JSX 标签的 'children' 属性期望类型 'never' 需要多个孩子,但只提供了一个孩子。ts(2745)
No overload matches this call.
没有重载匹配此调用。 This JSX tag's 'children' prop expects type 'never' which requires multiple children, but only a single child was provided.ts(2769)
这个 JSX 标记的 'children' 属性需要类型 'never',它需要多个孩子,但只提供了一个孩子。ts(2769)
Not sure what's wrong about my code since I think I followed most recommendations..不确定我的代码有什么问题,因为我认为我遵循了大多数建议..
Typescript template literal types are not as smart as you might think. Typescript 模板文字类型并不像您想象的那么聪明。 You might expect
h${props.level}
to evaluate to a union type "h1" | "h2" |...
您可能期望
h${props.level}
评估为联合类型"h1" | "h2" |...
"h1" | "h2" |...
based on the type of your props.level
variable. "h1" | "h2" |...
基于你的props.level
变量的类型。 Instead it is just string
.相反,它只是
string
。 So you will need an as
assertion somewhere in your code in order to declare that this string
is a valid key of JSX.IntrinsicElements
.因此,您需要在代码中的某处使用
as
断言,以声明此string
是JSX.IntrinsicElements
的有效键。
Getting the union "h1" | "h2" |...
获得联合
"h1" | "h2" |...
"h1" | "h2" |...
as a type is tough because Props['level']
is a union of number
literals rather than string
literals. "h1" | "h2" |...
作为一种类型很难,因为Props['level']
是number
文字而不是string
文字的联合。 But we don't really need the union because t doesn't really matter which heading type it is.但是我们并不真正需要联合,因为它是哪种标题类型并不重要。 You can use
as "h1"
and you'll be fine.你可以使用
as "h1"
,你会没事的。
export default function Heading(props: Props) {
return <S.Heading as={`h${props.level}` as "h1"}>{props.children}</S.Heading>;
}
Out of curiosity I wanted to see if I could extract the valid h*
tags from JSX.IntrinsicElements
.出于好奇,我想看看是否可以从
JSX.IntrinsicElements
中提取有效的h*
标签。 I came up with a solution that almost works based on string length, but I forgot about hr
!我想出了一个几乎可以根据字符串长度工作的解决方案,但我忘记了
hr
!
type HTag = {
[K in keyof JSX.IntrinsicElements]: K extends `h${string}${infer B}` ? B extends "" ? K : never : never
}[keyof JSX.IntrinsicElements]
evaluates to:评估为:
"h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "hr"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.