メインコンテンツまでスキップ

オブジェクトのサブセットを得る

オブジェクトのサブセットを得る方法です。サブセットとは、あるオブジェクトのいち部分を切り取ったもので、ここで紹介する方法は、プロパティ名を指定してオブジェクトの一部分を切り出すものです。たとえば、次のような数多くのプロパティを持つオブジェクトがあるとき、ここから数個のプロパティだけを持つオブジェクトを作る方法です。

ts
const profile = {
name: "suin",
twitter: "suin",
github: "suin",
country: "JP",
prefecture: "東京都",
city: "千代田区",
address: "丸の内2-4-1",
building: "丸ビル",
zipcode: "100-6390",
};
 
// 上の9つプロパティを持つオブジェクトから、下の6つのプロパティだけを抽出したオブジェクトを得たい
 
const address = {
country: "JP",
prefecture: "東京都",
city: "千代田区",
address: "丸の内2-4-1",
building: "丸ビル",
zipcode: "100-6390",
};
ts
const profile = {
name: "suin",
twitter: "suin",
github: "suin",
country: "JP",
prefecture: "東京都",
city: "千代田区",
address: "丸の内2-4-1",
building: "丸ビル",
zipcode: "100-6390",
};
 
// 上の9つプロパティを持つオブジェクトから、下の6つのプロパティだけを抽出したオブジェクトを得たい
 
const address = {
country: "JP",
prefecture: "東京都",
city: "千代田区",
address: "丸の内2-4-1",
building: "丸ビル",
zipcode: "100-6390",
};

方法1: 即時関数・分割代入・shorthand property nameの合わせ技

オブジェクトのサブセットを得る1つ目の方法は、即時関数と分割代入、そして、shorthand property nameを組み合わせる方法です。

ts
const sns = (({ twitter, github }) => ({ twitter, github }))(profile);
//=> {
// "twitter": "suin",
// "github": "suin"
// }
ts
const sns = (({ twitter, github }) => ({ twitter, github }))(profile);
//=> {
// "twitter": "suin",
// "github": "suin"
// }

この方法のメリットとデメリットは次のとおりです。

  • メリット
    • 外部ライブラリを必要としない。
  • デメリット
    • 初見の読み手には意外性のあるコードに見える場合がある。
    • 即時関数の引数部分とshorthand property nameの2箇所に同じプロパティ名を書く必要があり冗長。

この書き方は、数個の少ないプロパティを抽出したいときは便利ですが、たくさんのプロパティを抽出しようとすると記述量が増え、徐々に大変さが出てきます。

抽出したいプロパティよりも、除きたいプロパティのほうが少ない場合は、次のような書き方で除きたいプロパティを指定するほうが簡単です。

ts
const address = (({ name, twitter, github, ...rest }) => rest)(profile);
const address: { country: string; prefecture: string; city: string; address: string; building: string; zipcode: string; }
//=> {
// "country": "JP",
// "prefecture": "東京都",
// "city": "千代田区",
// "address": "丸の内2-4-1",
// "building": "丸ビル",
// "zipcode": "100-6390"
// }
ts
const address = (({ name, twitter, github, ...rest }) => rest)(profile);
const address: { country: string; prefecture: string; city: string; address: string; building: string; zipcode: string; }
//=> {
// "country": "JP",
// "prefecture": "東京都",
// "city": "千代田区",
// "address": "丸の内2-4-1",
// "building": "丸ビル",
// "zipcode": "100-6390"
// }

JavaScriptでは、deleteを使うとオブジェクトからプロパティを取り除けるので、上の書き方はまどろっこしいと思われるかもしれません。この書き方をするには理由があって、TypeScriptではdeleteの使い勝手が良くないからです。あるオブジェクトからdeleteを使ってプロパティを取り除きたい場合、TypeScriptではそのプロパティがオプショナルでなければなりません。

ts
const address = { ...profile };
delete address.name;
The operand of a 'delete' operator must be optional.2790The operand of a 'delete' operator must be optional.
ts
const address = { ...profile };
delete address.name;
The operand of a 'delete' operator must be optional.2790The operand of a 'delete' operator must be optional.

方法2: lodash.pick / lodash.omit

2つ目の方法はlodashを用いるものです。lodashはさまざまな便利関数を提供するライブラリで、その中のひとつにpickというオブジェクトのサブセットを得るための関数があります。

ts
import _ from "lodash";
 
const sns = _.pick(profile, ["twitter", "github"]);
//=> {
// "twitter": "suin",
// "github": "suin"
// }
ts
import _ from "lodash";
 
const sns = _.pick(profile, ["twitter", "github"]);
//=> {
// "twitter": "suin",
// "github": "suin"
// }

lodash全体ではなく、pick関数だけが必要な場合は、パッケージlodash.pickを使うこともできます。この場合、次のようにしてpick関数を使います。

ts
import pick from "lodash.pick";
 
const sns = pick(profile, ["twitter", "github"]);
ts
import pick from "lodash.pick";
 
const sns = pick(profile, ["twitter", "github"]);

lodash.pickのメリットとデメリットは次のとおりです。

  • メリット
    • 宣言的で読みやすい。
    • 記述量が少ない。
  • デメリット
    • ライブラリを導入する必要がある。

lodash.pickは抽出したいプロパティ名を指定する関数ですが、抽出したいプロパティより除外したいプロパティが少ない場合は、lodash.omitを使ったほうが便利です。

ts
import _ from "lodash";
 
const address = _.omit(profile, ["name", "twitter", "github"]);
//=> {
// "country": "JP",
// "prefecture": "東京都",
// "city": "千代田区",
// "address": "丸の内2-4-1",
// "building": "丸ビル",
// "zipcode": "100-6390"
// }
ts
import _ from "lodash";
 
const address = _.omit(profile, ["name", "twitter", "github"]);
//=> {
// "country": "JP",
// "prefecture": "東京都",
// "city": "千代田区",
// "address": "丸の内2-4-1",
// "building": "丸ビル",
// "zipcode": "100-6390"
// }

lodash、lodash.pickとlodash.omitのインストールは次のコマンドで行なえます。

bash
# lodashのインストール
npm install lodash
npm install -D @types/lodash
# lodash.pickとlodash.omitのインストール
npm install lodash.pick lodash.omit
npm install -D @types/lodash.pick @types/lodash.omit
bash
# lodashのインストール
npm install lodash
npm install -D @types/lodash
# lodash.pickとlodash.omitのインストール
npm install lodash.pick lodash.omit
npm install -D @types/lodash.pick @types/lodash.omit
  • 質問する ─ 読んでも分からなかったこと、TypeScriptで分からないこと、お気軽にGitHubまで🙂
  • 問題を報告する ─ 文章やサンプルコードなどの誤植はお知らせください。