投稿日:2021年4月11日
この記事ではTypeScriptでオブジェクトにgetter、setterを簡単に追加する方法について解説しています。
この記事では以下の環境を前提にしています。
結論からいうと以下の用にkeyofを使うことで実装することができます。
// ユーザー
type User = {
name: string;
age: number;
email: string;
};
// 与えられたUserオブジェクトをアクセサーに変更する
function MagicUser(user: User) {
// すべてのgetter
function get<K extends keyof User>(key: K) {
return user[key];
}
// すべてのsetter
function set<K extends keyof User>(key: K, value: typeof user[K]) {
user[key] = value;
return user;
}
return {
get,
set,
};
}
const user: User = {
name: "marsquai",
age: 26,
email: "example@marsquai.com",
};
const magicUser = MagicUser(user);
console.log(magicUser.get("name")); // [ out ] marsquai
console.log(magicUser.get("position")); // Compile Error
magicUser.set("age", 100);
magicUser.set("age", "marsmars"); // Compile Error
keyof TはTの許可されたプロパティ名のタイプを生成します。
今回のkeyof Userでは"name" | "age" | "email"という型が生成されるため、get()とset()で受け取るプロパティ名を制限できるわけですね。
実際に拡張されたオブジェクトのget()、set()メソッドを使ってみると、プロパティ名として受け取れる値が文字列の"name"、"age"、"email"だけであることがわかると思います。
さらに以下の様にジェネリックの関数にしておくとより便利かもしれません。
// 与えられたオブジェクトをアクセサーに変更する
function MagicObj(obj: T) {
// すべてのgetter
function get<K extends keyof T>(key: K) {
return obj[key];
}
// すべてのsetter
function set<K extends keyof T>(key: K, value: typeof obj[K]) {
obj[key] = value;
return obj;
}
return {
get,
set,
};
}