打字稿高阶组件

Posted

技术标签:

【中文标题】打字稿高阶组件【英文标题】:Typescript higher order component 【发布时间】:2019-06-21 10:30:32 【问题描述】:

我在输入以下 HOC 时遇到问题。我已经对其进行了简化,但用例是根据新道具修改包装组件上的类。

import React,  ComponentType  from 'react';

interface Classable 
  className?: string;


interface Fooable 
  foo: string;


function fooTheClass(foo: string, className?: string): string 
  // this is a simplified example..
  return className ? `$(className) $foo` : foo;


// HOC to modify className based on a new prop.
const withFoo = <P extends Classable>(Component: ComponentType<P>): ComponentType<P & Fooable> => 
  const newComponent = ( foo, className, ...rest : P & Fooable) => 
    return <Component className=fooTheClass(foo, className) ...rest />;
  ;
  return newComponent;
;

这会导致以下错误:

类型 ' 类名:字符串; & Pick>' 不可分配给类型 'IntrinsicAttributes &P&children?:ReactNode; '。输入'类名:字符串; & 选择>' 不是 可分配给类型“P”。 [2322]

不解构可以消除错误:

const withFoo1 = <P extends Classable>(Component: ComponentType<P>): ComponentType<P & Fooable> => 
  const newComponent = (props: P & Fooable) => 
    const  ...rest  = props;
    rest.className = fooTheClass(rest.foo, rest.className);
    delete rest.foo;
    return <Component ...rest  />;
  ;
  return newComponent;
;

或显式转换:

const withFoo2 = <P extends Classable>(Component: ComponentType<P>): ComponentType<P & Fooable> => 
  const newComponent = ( foo, className, ...rest : P & Fooable) => 
    return <Component className=fooTheClass(foo, className) ...(rest as unknown as P) />;
  ;
  return newComponent;
;

(请注意:

return <Component className=fooTheClass(foo, className) ...(rest as P) />;

不会工作)。

这两个似乎都是不优雅的解决方法。有没有更好的办法?

【问题讨论】:

【参考方案1】:

我认为你能做的最好的事情是使用预定义的React.FC 类型而不是直接输入道具:

const withFoo = <P extends Classable>(
  Component: ComponentType<P>
): ComponentType<P & Fooable> => 
  const newComponent: React.FC<P & Fooable> = ( foo, className, ...rest ) => 
    return <Component className=fooTheClass(foo, className) ...rest as P />;
  ;
  return newComponent;
;

【讨论】:

以上是关于打字稿高阶组件的主要内容,如果未能解决你的问题,请参考以下文章

在打字稿组件中使用'import * as'会出错 -

在 Angular 1.5 中绑定组件函数时如何利用打字稿?

打字稿扩展反应原生视图组件

使用样式组件的打字稿错误

打字稿如何在父组件中传递道具

单元测试一个打字稿vue组件