创建一个返回反应组件类的打字稿函数

Posted

技术标签:

【中文标题】创建一个返回反应组件类的打字稿函数【英文标题】:Create a typescript function returning react component class 【发布时间】:2020-06-03 19:17:55 【问题描述】:

我需要创建一个实用函数,它将根据某些条件返回一个反应组件类(而不是实例)。所以函数的返回类型应该是泛型的(React.PureComponent)

import React from 'react';
class FooOne extends React.PureComponent 
    render(): React.ReactElement 
        return null;
    

class FooTwo extends React.PureComponent 
    render(): React.ReactElement 
        return null;
    

function getFooClass(condition: boolean): typeof React.PureComponent 
    return condition ? FooOne : FooTwo;

const SomeFooClass = getFooClass(true);
const instance: React.PureComponent = new SomeFooClass();

上面的代码倾向于工作(我仍然不明白为什么我需要使用 typeof React.PureComponent 作为 getFooClass 的返回类型,这是通过实验发现的), 但是 typescript 会为 getFooClass 生成以下错误:

Type 'typeof FooOne' is not assignable to type 'typeof PureComponent'.
  Construct signature return types 'FooOne' and 'PureComponent<P, S>' are incompatible.
    The types of 'props' are incompatible between these types.
      Type 'Readonly< children?: ReactNode; > & Readonly<>' is not assignable to type 'Readonly< children?: ReactNode; > & Readonly<P>'.
        Type 'Readonly< children?: ReactNode; > & Readonly<>' is not assignable to type 'Readonly<P>'.

也许这是一种打字稿错误或限制?

【问题讨论】:

您使用的是哪个版本的打字稿? This works... 关于typeof - 需要表明您正在返回构造函数而不是实例。顺便说一句,为什么需要使用new SomeFooClass.. 手动实例化组件?只是好奇 @AlekseyL.,新的 SomeFooClass 看起来真的很奇怪,这实际上是个坏例子。它是如何使用的:class AnotherComponent extends Component const GenericEditor = getFooClass(this.state.condition); render() return &lt;div&gt;&lt;GenericEditor /&gt;&lt;/div&gt; 当函数返回一些组件(不是实例)时,最好使用更通用的React.ComponentType - function getFooClass(condition: boolean): React.ComponentType AlekseyL.,另一个假设,我的问题是由 @types/react 中的错误引起的。您在 Playground 的示例中使用了 react 16,而我的项目对应的是旧的 react 版本 15 和旧的 @types 包。 【参考方案1】:

试试类似的东西

function getFooClass(condition: boolean): React.ComponentType 
   // if FooOne and FooTwo have arguments you can use React.ComponentType<TArgs>
   return condition ? FooOne : FooTwo;

用法应该是这样的

function render() 
    const FooEl = getFooClass(true); // PascalCase is required
    return <FooEl />

或者直接返回创建的实例

function getFooClass(condition: boolean): JSX.Element  
   return condition ? <FooOne /> : <FooTwo />;

【讨论】:

【参考方案2】:

React.ReactNode 在这种情况下应该可以工作:

function getFooClass(condition: boolean): React.ReactNode 
  return condition ? FooOne : FooTwo;

【讨论】:

这不会编译,应该使用React.ComponentType。但即使使用React.ComponentTypenew SomeFooClass() 也不会被允许 对不起.. 我现在明白了:/ @AlekseyL。使用 React.ReactNode 将编译 答案已更新 - 这是反应 TS 事物的绝佳资源github.com/typescript-cheatsheets/react-typescript-cheatsheet 现在完全错了,React.ReactNode 是渲染的结果,而不是组件的类型github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/…

以上是关于创建一个返回反应组件类的打字稿函数的主要内容,如果未能解决你的问题,请参考以下文章

在打字稿中返回反应 16 个数组元素

使用打字稿创建自定义反应路由组件。类型上不存在属性“路径”... RouteProps

反应本机打字稿屏幕测试返回测试套件无法运行 AsyncStorage 为空

避免任何类型在打字稿中获取枚举值

修改返回数据,然后在打字稿/离子中返回承诺

基于属性的打字稿方法返回类型