TypeScript で Redux の型定義から強く型付けされた Redux ミドルウェアを作成するにはどうすればよいでしょうか? 質問する

TypeScript で Redux の型定義から強く型付けされた Redux ミドルウェアを作成するにはどうすればよいでしょうか? 質問する

私は React と Redux を使用する TypeScript プロジェクトを持っており、ミドルウェア関数をいくつか追加しようとしています。まず、次のように Redux のサンプルから 1 つを実装することから始めました。

// ---- middleware.ts ----
export type MiddlewareFunction = (store: any) => (next: any) => (action: any) => any;

export class MyMiddleWare {
    public static Logger: MiddlewareFunction = store => next => action => {
        // Do stuff
        return next(action);
    }
}

// ---- main.ts ---- 
import * as MyMiddleware from "./middleware";

const createStoreWithMiddleware = Redux.applyMiddleware(MyMiddleWare.Logger)(Redux.createStore);

上記は問題なく動作しますが、これは TypeScript なので、強く型付けし、理想的には Redux で定義された型を使用して、独自の型を再発明して維持する必要がないようにしたいと思います。そこで、Redux の index.d.ts ファイルから関連する部分を抜粋します。

// ---- index.d.ts from Redux ----
export interface Action {
    type: any;
}

export interface Dispatch<S> {
    <A extends Action>(action: A): A;
}

export interface MiddlewareAPI<S> {
    dispatch: Dispatch<S>;
    getState(): S;
}

export interface Middleware {
    <S>(api: MiddlewareAPI<S>): (next: Dispatch<S>) => Dispatch<S>;
}

私は、これらの型を Logger メソッドに組み込む方法を見つけようとしていますが、あまりうまくいきません。次のようなものが機能するはずです。

interface MyStore {
    thing: string;
    item: number;
}

interface MyAction extends Action {
    note: string;
}

export class MyMiddleWare {
    public static Logger: Middleware = (api: MiddlewareAPI<MyStore>) => (next: Dispatch<MyStore>) => (action: MyAction) => {
        const currentState: MyStore = api.getState();
        const newNote: string = action.note;
        // Do stuff
        return next(action);
    };
}

しかし、代わりに次のエラーが発生します:

エラー TS2322: タイプ '(api: MiddlewareAPI) => (next: Dispatch) => (action: Action) => Action' は、タイプ 'Middleware' に割り当てることができません。
パラメータのタイプ 'api' と 'api' は互換性がありません。
タイプ 'MiddlewareAPI' は、タイプ 'MiddlewareAPI' に割り当てることができません。
タイプ 'S' は、タイプ 'MyStore' に割り当てることができません。

型定義でジェネリック <S> が宣言されているのを確認しましたが、さまざまな組み合わせを試してみましたが、残りの宣言でジェネリック型として認識されるように MyStore として指定する方法がわかりません。たとえば、宣言によると、api.getState() は MyStore オブジェクトを返す必要があります。もちろん、アクション型 <A> にも同じ考え方が適用されます。

ベストアンサー1

MyStore は必須ではありません。

export const Logger: Middleware =
  (api: MiddlewareAPI<void>) => 
  (next: Dispatch<void>) => 
  <A extends Action>(action: A) => {
    // Do stuff
   return next(action);
  };

または

export const Logger: Middleware = api => next => action => {
  // Do stuff
  return next(action);
};

良い開発を

おすすめ記事