React的`memo`将泛型放入返回的函数中

Max*_*don 7 typescript reactjs

我想将React memo用于具有通用参数的函数。不幸的是,泛型参数默认为泛型,所有奇特的泛型推导逻辑都丢失了(TypeScript v3.5.2)。在下面的示例中WithMemo(使用React.memo)失败,原因:

Property 'length' does not exist on type 'string | number'.
  Property 'length' does not exist on type 'number'.
Run Code Online (Sandbox Code Playgroud)

WithoutMemo作品如预期的那样。

interface TProps<T extends string | number> {
  arg: T;
  output: (o: T) => string;
}

const Test = <T extends string | number>(props: TProps<T>) => {
  const { arg, output } = props;
  return <div>{output(arg)} </div>;
};

const myArg = 'a string';
const WithoutMemo = <Test arg={myArg} output={o => `${o}: ${o.length}`} />;

const MemoTest = React.memo(Test);
const WithMemo = <MemoTest arg={myArg} output={o => `${o}: ${o.length}`} />;
Run Code Online (Sandbox Code Playgroud)

我已经看过这个问题,但我认为它与我的问题无关。

可能的解决方案

我发现了使用通用接口的可能解决方案,但似乎有些粗糙:

const myArgStr = 'a string';
const myArgNo: number = 2;
const WithoutMemo = (
  <>
    <Test arg={myArgStr} output={o => `${o}: ${o.length}`} />
    <Test arg={myArgNo} output={o => `${o * 2}`} />
  </>
);

interface MemoHelperFn {
  <T extends string | number>(arg: TProps<T>): JSX.Element;
}

const MemoTest: MemoHelperFn = React.memo(Test);
const WithMemo = (
  <>
    <MemoTest arg={myArgStr} output={o => `${o}: ${o.length}`} />
    <MemoTest arg={myArgNo} output={o => `${o * 2}`} />
  </>
);

// Below fail as expected
const FailsWithoutMemo = (
  <>
    <Test arg={myArgNo} output={o => `${o}: ${o.length}`} />
    <Test arg={myArgStr} output={o => `${o * 2}`} />
  </>
);

const FailsWithMemo = (
  <>
    <MemoTest arg={myArgNo} output={o => `${o}: ${o.length}`} />
    <MemoTest arg={myArgStr} output={o => `${o * 2}`} />
  </>
);
Run Code Online (Sandbox Code Playgroud)

是否有解决此问题的更优雅的主意?

Raf*_*cio 6

来自/sf/answers/4211929781/

    interface ISomeComponentWithGenericsProps<T> { value: T; } 

    function SomeComponentWithGenerics<T>(props: ISomeComponentWithGenericsProps<T>) {
      return <span>{props.value}</span>;
    }

    export default React.memo(SomeComponentWithGenerics) as typeof SomeComponentWithGenerics;

Run Code Online (Sandbox Code Playgroud)


Dan*_*ald 0

作为解决方法,我们可以在组件内使用 useMemo。应该足够好了。