web-dev-qa-db-ja.com

Typescript with React-ジェネリックコンポーネントクラスでHOCを使用する

私は一般的なReactコンポーネントを持っています、次のように言います:

_class Foo<T> extends React.Component<FooProps<T>, FooState> {
    constructor(props: FooProps<T>) {
        super(props);

    render() {
        return <p> The result is {SomeGenericFunction<T>()}</p>;
    }
}
_

私はこれに似たHOCも持っています(しかしあまり意味がありません):

_export const withTd = 
    <T extends WithTdProps>(TableElement: React.ComponentType<T>): React.SFC<T> => 
(props: T) => <td><TableElement {...props}/></td>;
_

しかし、私がこのようなコンポーネントを使用するとき:

_const FooWithTd = withTd(Foo);
_

withTd(Foo<T>)FooWithTdも実行できないため、型引数を渡す方法はありません。型は常に間違っています。それを行うための適切な方法は何ですか?

編集:問題は、HOCでTに必要なタイプがわからないため、後で_<FooWithTd<number> {...someprops}/>_のようなものを使用できるようにしたいということです。

9
Joald

回避策:単純なケース

コンポーネントのtypeパラメーターが小道具に渡すためだけに使用され、コンポーネントのユーザーが小道具を渡してレンダリングする以外の機能を期待していない場合は、hoc(...args)(Component)の結果を明示的にハードキャストできます。次のように、Reactの機能コンポーネントタイプに変更します。

import React, {ReactElement} from 'react';

class MyComponent<T> extends React.Component<MyProps<T>> { /*...*/ }

const kindaFixed = myHoc(...args)(MyComponent) as unknown as <T>(props: MyProps<T>) => ReactElement;

回避策:より複雑で、実行時のコストがかかる

here :と想定されるファブリックのような関数を使用できます。

class MyComponent<T> extends React.Component<MyProps<T>> { /*...*/ }

export default function MyComponentFabric<T>() {
    return hoc(...args)(MyComponent as new(props: MyProps<T>) => MyComponent<T>);
}

これでは、使用するタイプごとに、ラップされたコンポーネントの新しいバージョンを作成する必要があります。

import MyComponentFabric from '...whenever';

const MyComponentSpecificToStrings = MyComponentFabric<string>();

これにより、コンポーネントのすべてのパブリックインスタンスフィールドとメソッドにアクセスできるようになります。

概要

react-reduxExampleGenericComponent<T>からconnectを使用しようとしたときに、この問題に直面しました。残念ながら、TypeScriptがHKTをサポートするまでは適切に修正できず、使用するHOCは、この機能を尊重して型を更新します。

コンポーネントインスタンスのフィールドとメソッドにアクセスする必要がある場合、レンダリング以外の使用法については(少なくとも今のところ)正しい解決策がない可能性があります。 「正しい」とは、「醜い明示的なタイプキャストなし」、および「実行時コストなし」を意味します。

試すことができることの1つは、クラスコンポーネントを2つのコンポーネントに分割することです。1つはHOCで使用され、もう1つは必要なフィールドとメソッドを提供します。