🔌
バニラTS(JS)でインターフェース分離の原則から状態を管理するTips
目次
概要
ReactやVue.jsを使用しているとコンポーネント内の状態を定義して更新するということが簡単に実装可能であり、どこで管理されているかも分かりやすくなります。
しかし、そのようなライブラリやフレームワークを使用していない場合、決まったルールを定めない限り、状態が管理されずに状態を更新するコードが散らばってしまいます。
そこで今回は非常に短いですが、SOLIDの原則の1つであるインターフェース分離の原則を使用して、ViteのVanillaTSの初期コードにあるカウンターの状態管理を行います。
実装
state.ts
export interface Counter {
count: number;
readonly addNumber: number;
}
interface State extends Counter {
readonly limit: number;
}
export const State: State = {
count: 100,
limit: 1000,
addNumber: 2,
};
counter.ts
import { Counter } from "./state";
export function setupCounter(element: HTMLButtonElement, state: Counter) {
const setCounter = (count: number) => {
state.count = count;
element.innerHTML = `count is ${state.count}`;
};
element.addEventListener("click", () =>
setCounter(state.count + state.addNumber)
);
setCounter(state.count);
}
main.ts
import { State } from "./state.ts";
import { setupCounter } from "./counter.ts";
/**
* 省略
*/
setupCounter(document.querySelector<HTMLButtonElement>("#counter")!, State);
まとめ
今回のコードでは、まずstate.ts
のState
オブジェクトにて状態を宣言しています。
setupCounter
関数はCounter
型の引数を取ることで、この関数は状態となるState
オブジェクトではなくともCounter
インターフェースを実装するオブジェクトであれば、実行可能な関数となっています。
ここで、setupCounter
関数のためのインターフェースであるCounter
を個別に用意しState
がそれを実装することで、インターフェースがクライアント毎に分離されインターフェースの責務が単一となり、インターフェース分離の原則に沿った形となります。
もし、状態を参照する関数が増えた場合はState
が実装するインターフェースをその関数のために用意し実装する形となります。
Discussion