在Typescript中强制传递普通HTML元素作为子元素

huangapple go评论58阅读模式
英文:

Enforce Plain HTML Element Passed as Children in Typescript

问题

我正在尝试创建一个React组件,该组件强制其子元素为纯HTML元素(例如<p>...</p>)而不是React组件(例如<SomeComponent/>)。

这是我尝试过的一些代码,但没有成功

import React from "react";

interface ITooltipProps {
  // 目标是要求这里有一个纯HTML子元素,即<p>...</p>,如果得到其他任何东西则出错
  // children: React.ReactElement<JSX.IntrinsicElements[keyof JSX.IntrinsicElements]>;

  // 这不起作用,因为JSX.IntrinsicElements映射只返回props,而不是元素类型
  // children: JSX.IntrinsicElements[keyof JSX.IntrinsicElements];
  
  // 这不起作用,因为它只是要求一个可以接受HTML元素的props的React组件(所有这些都是可选的)
  children: React.ReactElement<JSX.IntrinsicElements[keyof JSX.IntrinsicElements]>;
}

export function Tooltip({
  children
}: ITooltipProps) {
  return (
    <div>
        {children}
    </div>
  )
}

// 一个元素,不返回纯HTML子元素
const F = () => {
  return (
    <>
        <p>Hello</p>
        <p>World</p>
    </>
  )
}

const x = (
    // 期望<F/>出错,因为F不返回纯HTML对象/返回片段
  <Tooltip>
    <F/>
  </Tooltip>
)

这是一个带有上述代码的TS Playground链接

想知道是否有人知道如何强制组件的子元素是“原始”HTML元素,而不是React组件 - 谢谢!

英文:

I'm trying to create a React component which enforces that its children are plain HTML elements (such as &lt;p&gt;...&lt;/p&gt;) and not React components (such as &lt;SomeComponent/&gt;)

Here's some code I've tried, to no avail

import React from &quot;react&quot;

interface ITooltipProps {
  // Goal is to require a plain HTML child here, i.e. &lt;p&gt;...&lt;/p&gt;, and error if we get anything else
  // children: React.ReactElement&lt;JSX.IntrinsicElements[keyof JSX.IntrinsicElements]&gt;;

  // This doesn&#39;t work because the JSX.IntrinsicElements map just returns props, not the element type
  // children: JSX.IntrinsicElements[keyof JSX.IntrinsicElements];
  
  // This doesn&#39;t work because it&#39;s just asking for a react component that can take props of an HTML element (all of which are optional)
  children: React.ReactElement&lt;JSX.IntrinsicElements[keyof JSX.IntrinsicElements]&gt;;
}

export function Tooltip({
  children
}: ITooltipProps) {
  return (
    &lt;div&gt;
        {children}
    &lt;/div&gt;
  )
}

// An element which doesn&#39;t return a plain HTML child
const F = () =&gt; {
  return (
    &lt;&gt;
        &lt;p&gt;Hello&lt;/p&gt;
        &lt;p&gt;World&lt;/p&gt;
    &lt;/&gt;
  )
}

const x = (
    // Expect &lt;F/&gt; to error, since F isn&#39;t returning a plain HTML object / is returning a fragment
  &lt;Tooltip&gt;
    &lt;F/&gt;
  &lt;/Tooltip&gt;
)

(Here's a link to a TS playground with the above code)

Am wondering if anybody knows how to enforce that a component's children are "primitive" HTML elements, as opposed to react components – thanks!

答案1

得分: 1

这不可能。

渲染的 JSX 具有 JSX.Element 的返回类型,无论它包含什么。因此,普通的 HTML、片段或渲染的组件都具有相同的类型。这意味着你不能用类型以这种方式来约束它。

查看此示例

英文:

This is not possible.

Rendered JSX has a return type of JSX.Element no matter what it contains. So plain html, a fragment, or a rendered component all have the same type. Which means you can't use types to constrain it in this way.

See this playground

huangapple
  • 本文由 发表于 2023年6月13日 07:17:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76460826.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定