如何在 React.memo 中使用带有泛型的 Props

Dom*_*nic 2 javascript typescript reactjs

我正在尝试将以下内容转换为使用React.memo

interface Props<TRowData> {
  // props...
}

export function Table<TRowData>({
  propA,
  propB
}: Props<TRowData>) {

}
Run Code Online (Sandbox Code Playgroud)

像这样(不正确):

interface Props<TRowData> {
  // props...
}



export const Table = memo<Props<TRowData>>(
({
  propA,
  propB
}) => {

})
Run Code Online (Sandbox Code Playgroud)

如何更正此语法?目前它有这个错误:

// Cannot find name 'TRowData'.
export const Table = memo<Props<TRowData>>(
                                ~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

Dom*_*nic 22

我通过将备忘录和非备忘录分开并进行一些类型转换来解决这个问题:

const TableComponent = <T,>(props: TableComponentProps<T>) => {
 // ...
}

// or
function TableComponent<T>(props: TableComponentProps<T>) {
  // ...
}

Run Code Online (Sandbox Code Playgroud)

然后:

export const Table = memo(TableComponent) as typeof TableComponent
Run Code Online (Sandbox Code Playgroud)

或者:

const typedMemo: <T>(c: T) => T = React.memo
export const Table = typedMemo(TableComponent)
Run Code Online (Sandbox Code Playgroud)


for*_*d04 7

使用当前的 React 类型声明,不可能从React.memo. 没有类型断言的解决方案是添加额外的memo函数重载以利用 TS 3.4高阶函数类型推断

import React, { memo } from "react"

declare module "react" { // augment React types
  function memo<A, B>(Component: (props: A) => B): (props: A) => ReactElement | null
  // return type is same as ReturnType<ExoticComponent<any>>
}
Run Code Online (Sandbox Code Playgroud)

然后,您将能够使Table组件通用。只需确保将通用函数传递给memo

interface Props<T> {
  a: T
}

const TableWrapped = <T extends {}>(props: Props<T>) => <div>{props.a}</div>

const Table = memo(TableWrapped)

const App = () => (
  <>
    <Table a="foo" /> {/* (props: Props<string>) => ... */}
    <Table a={3} /> {/* (props: Props<number>) => ... */}
  </>
)
Run Code Online (Sandbox Code Playgroud)

操场