LoginSignup
9
4

More than 5 years have passed since last update.

Redux/Mobxを使ったときのTypeScriptの型エラーの解決策

Posted at

問題

React/TypeScriptでreduxやmobxを使用した場合、コンポーネントのプロパティに関する型エラーが出ることがあります。例えば、以下のようにmobxProviderを用いて暗にmessageStoreを注入したとします。

import { observable } from "mobx";
import { inject, observer, Provider } from "mobx-react";
import * as React from "react";
import * as ReactDOM from "react-dom";

class MessageStore {
    @observable public message: string = "";
}

@inject("messageStore")
@observer
class App extends React.Component<{ messageStore: MessageStore }> {
    public render() {
        return <div>{this.props.messageStore.message}</div>;
    }
}

const messageStore = new MessageStore();

ReactDOM.render(
    <Provider messageStore={messageStore}><App /></Provider>,
    document.getElementById("root"));

上記のコードをコンパイルしようとすると以下のエラーが出ます。

Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<App> & Readonly<{ children?: ReactNode; }> & Reado...'.
  Type '{}' is not assignable to type 'Readonly<{ messageStore: MessageStore; }>'.
    Property 'messageStore' is missing in type '{}'.

これは<App />でコンポーネントを使用するときにmessageStoreのプロパティが渡されていないために起こります。しかし、実際にはProviderによって暗に渡されているためこのコードは正しく動作します。問題はmobxのinjectデコレータが元のクラス型を上手く加工してくれないことです。因みに、reduxのconnect関数の使用時にも似たような問題が起こります。

解決策

React.Componentの型引数にanyを渡したくなりますが、もう少しいい方法があります。messageStoreをオプショナルにします。この場合でも、いちいちmessageStoreがプロパティに存在するか確認しなくてもthis.props.messageStoreで使用できます。

class App extends React.Component<{ messageStore?: MessageStore }> {
    ...
}

Partial型を使うとstoreが複数ある場合に便利です。

interface IStore { 
    messageStore: MessageStore;
    anotherStore: AnotherStore;
}

class App extends React.Component<Partial<IStore>> {
    ...
}
9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4