【问题标题】:In Typescript, is there any way to typecheck passed-in JSX.Element's?在 Typescript 中,有没有办法对传入的 JSX.Elements 进行类型检查?
【发布时间】:2017-08-14 18:55:48
【问题描述】:

考虑这个简单的案例:

图书馆客户:

class ClientComponent extends React.Component<any,any> {
    render() {
        const myNestedElement = (<LibNestedComponent/>)
        return <LibComponent nested={myNestedElement}/> 
    }
}

图书馆:

class LibNestedComponent extends React.Component<any,any> {
    render() { return <div>nested stuff</div> }
}

interface LibComponentProps { nested: JSX.Element }
class LibComponent  extends React.Component<LibComponentProps,any> {
    render() {
        return <div>{this.props.nested}</div>
    }
}

作为 Lib 的作者,我希望能够通过 LibComponentProps 接口告诉我的 LibComponent 客户,传入的 nested 属性必须是 LibNestedComponent 类型的元素 -不仅仅是任何旧的 j.random 元素。但是AFAICT,没有办法做到这一点; Typescript doc 甚至说:

JSX 结果类型。 默认情况下,JSX 表达式的结果类型为 any。您可以通过指定JSX.Element 来自定义类型 界面。但是,无法检索类型信息 关于 JSX 的元素、属性或子元素,来自 this 界面。这是一个黑盒子。

有没有人可以轻松实现这种类型检查的解决方法?

(这个例子是故意的,并不意味着是一个合理的用例。)

【问题讨论】:

  • 我看到了一些关于限制父/子组件的基于类型的方法的问题,但据我所知,没有。
  • 对于任何元素,您可以将类型指定为React.ReactElement&lt;LibComponentProps&gt;,这会将传入的嵌套道具限制为LibComponentProps之一。
  • @HardikModha 我不确定你的意思是如何使用ReactElement,但 AFAICT 要么不正确,要么不强制,要么不正确。你能说明你的意思吗?
  • react的类型定义可以看出JSX.Element扩展了接口ReactElement。可能是这样,您可以使用React.ReactElement&lt;P&gt; 而不是JSX.Element。由于您可以将类型接口作为泛型参数传递,因此它将 prop 限制为您提供的类型之一。但仍然不确定这是您想要的。
  • @HardikModha 这不限制元素的种类 - 只有它的参数。不过,总比没有好!我错误地认为它没有被强制执行,但在道具界面祖先中找到了[name: string]: any,它为任何东西打开了谷仓的门。谢谢!

标签: reactjs typescript jsx


【解决方案1】:

除了我的评论,我不知道是否有打字稿的方式来限制客户端组件可以通过的组件类型。但是有一种方法可以让您确定作为 prop 传递的组件的类型。

您可以检查传递的组件的名称,看看它是哪种类型。

if (this.props.nested.type.name === 'LibNestedComponent') {
   console.log('A valid component is passed');
} else {
   console.log('Invalid component is passed');
}

其中nested 是您在提供的示例中传递的组件。

在下图中,您可以看到组件的名称。

但同样,这将是一个运行时检测。

【讨论】:

    【解决方案2】:

    您可以使用对象检查this.props.nested的类型

    if (this.props.nested.type !== LibNestedComponent) {
       throw new Error('Invalid prop passed. Make sure that an instance of LibNestedComponent is passed through the nested prop')
    }
    

    Hardik 的答案的问题是,如果您的代码被缩小,type.name 的值将会改变,您的代码将会失败。所以你应该直接使用type 属性。

    【讨论】:

    • 谢谢...不过我试图找到一个编译时验证!
    猜你喜欢
    • 2020-04-08
    • 2017-03-10
    • 2022-01-06
    • 1970-01-01
    • 2018-02-24
    • 2017-06-21
    • 1970-01-01
    • 2014-02-08
    • 2021-09-26
    相关资源
    最近更新 更多