ウェブサイト検索

reactjs - なぜ super() は不変のレコードに設定できないのですか?


私は本当にシンプルな新しいReduxストアの状態を設定しています。

以前作成したReduxストアを「クローン」して簡略化しました。最初は状態、リデューサー、セレクター、アクションをそれぞれ1つだけで試し、その後、ツリー(以前のプロジェクトのようなもの)を作ってみましたが、変わりませんでした。package.jsonを確認したところ、Redux、React、ReactRedux、TypeScript などのバージョンは同じでした。

import { Record } from "immutable";

export enum officeLocations {
    cityOne = "CITYONE",
    cityTwo = "CITYTWO",
    none = "NONE",
    cityThree = "CITYTHREE",
    cityFour = "CITYFOUR"
}

export interface ILocationInfo {
    location: officeLocations;
}

const LocationInfoRecord = Record({
    location: officeLocations.none
});

export class LocationInfo extends LocationInfoRecord implements ILocationInfo {
    public location: officeLocations;

    constructor(props?: ILocationInfo) {
        // props ? super(props) : super(); <-- in older project I use this line instead of if-else... but here it tell me I cannot invoke super multiple times...
        if (props) {super(props);}
        else {super();}
        this.location = props ? props.location : officeLocations.none; // <- In my older code I don't need this line, for some reason it give me an error that location is not instantiated if I don't put this line
    }

    public with(values: Partial<ILocationInfo>) {
      return this.merge(values);
    }
}

問題なく動作すると思っています…しかし、TypeScriptでは問題なくコンパイルされますが、実行すると「super()」でクラッシュし、「エラー: 不変レコードに設定できません」と表示されます。

**

更新:

**

今日、何も変更せずに、これが私にこのエラーを出します:

タイプ '(location: LocationInfo, action: IAction) => Map' はタイプ 'Reducer' に割り当てられません。パラメータ 'LocationInfo' と 'state' のタイプが互換性がありません。タイプ 'Map | undefined' はタイプ 'LocationInfo' に割り当てられません。タイプ 'undefined' はタイプ 'LocationInfo' に割り当てられません。

そして今、元のコード、すなわちコードのコメントで説明されたものでも、このエラーが出ます。

このエラーは、私が「combineReducers」を呼び出したときに発生します。

    const settingsReducer = combineReducers({
       location: locationReducer,
       other: otherReducer
    });

回答 #1

Record は、不変のレコードを生成するファクトリーです。あなたのコードは、ファクトリー自体に location を代入しようとしており、ファクトリーの出力に対してではありません。

レコード型は、通常のJavaScriptクラスよりも制限が厳しいです。クラスコンストラクターを使用せず、それはつまりクラスプロパティも使用できないことを意味します(クラスプロパティは技術的にコンストラクターの一部だからです)。

Record Types は JavaScript のクラス形式で構文的に作成することができますが、結果として得られる Record 関数は実際にはクラスコンストラクタではなく、ファクトリ関数です。

TypeScriptはImmutableをうまく扱えません。両方とも構造の明示的な定義を望みますが、別のレベルと別の方法で行うため、冗長なコードを書くことになります。

なので location プロパティは TS のためだけのもので、実際には使用されません。そこに何かを割り当てようとすべきではないので、TS に魔法のように割り当てられると伝えるだけです:

public readonly location!: officeLocations

そして次に this.location=props ? props.location : officeLocations.none; を削除します

もし何らかの理由で入力を変更したい場合は、単にコンストラクタ内でそれを行い、すべてを super に渡してください:

constructor(values = {}, name) {
    values.location = values.location || officeLocations.none;
    super(values, name);
}

こちらは、TypeScriptでImmutable Recordsを使用する方法についての説明を含む記事です。