HOWTO · TypeScript

TypeScript を使用してオブジェクトを配列にプッシュする

このチュートリアルでは、TypeScript を使用してオブジェクトを配列にプッシュする方法を説明します。

このページの内容

このガイドを読めば、TypeScript を使用してオブジェクトを配列にプッシュする方法がわかります。

プロジェクトを初期化する

Vite を使用して、vanilla-ts を使用して新しいプロジェクトをすばやく開始します。 必要なパッケージをインストールした後、ガイドの残りの部分で使用する 2つのオブジェクト インターフェイスを作成します。

export interface Comment {
	rating: number;
	comment: string;
	author: string;
	date: string;
}

export interface Dish {
	id: number;
	name: string;
	image: string;
	category: string;
	description: string;
	comments: Comment[];
}

ご覧のとおり、内部に配列を持つ comments プロパティを持つ Dish オブジェクトがあります。 この配列は、Comment インターフェイスに続くオブジェクトに適合します。

目標は、新しいコメントを comments プロパティにプッシュすることです。 これを示すために、次のオブジェクトを例として使用します。

import {Dish, Comment} from "./interfaces";

export let pastaDish: Dish = {
	id: 124,
	name: "Carbonara Pasta",
	image: "pasta-carbonara.jpg",
	category: "Italian Food",
	description:
		"Italian pasta dish originating in Lazio based on eggs, cheese, extra virgin olive oil, pancetta or guanciale, and bacon with black pepper.",
	comments: [],
};

export let pastaComment: Comment = {
	rating: 5,
	comment: "Very tasty!",
	author: "Juan Diego",
	date: "04/14/2022",
};

array.push メソッドを使用して、TypeScript でオブジェクトを配列にプッシュする

配列から呼び出された場合、push は配列の末尾に 1つ以上の要素を追加します。 新しい配列を返すのではなく、元の配列を編集します。

comments プロパティからこのメソッドを呼び出して、新しい要素を追加できます。

import {Dish, Comment} from "./interfaces";
import {pastaDish, pastaComment} from "./pastaDish";

const addNewComment = (dish: Dish, newComment: Comment) => {
	dish.comments.push(newComment);
	console.log(dish.comments);
};

addNewComment(pastaDish, pastaComment);

期待される出力:

[
	{
		rating: 5,
		comment: "Very tasty!",
		author: "Juan Diego",
		date: "04/14/2022",
	},
];

TypeScript でオブジェクトを配列にプッシュ

ここで何が起こっているかを分析してみましょう: dish と newComment を引数として取る addNewComment という新しい関数を作成します。

次に、comments プロパティにアクセスし、newComment を唯一の引数としてその push メソッドを呼び出します。 これで、すでにオブジェクトを配列にプッシュしました。

コード例

array.concat メソッドを使用して、TypeScript でオブジェクトを配列にプッシュする

このソリューションは問題なく機能しますが、array.push メソッドは dish オブジェクトを変更します。 つまり、元の dish オブジェクトが変更されます。これは悪い習慣と見なされます。

突然変異は副作用です。プログラム内で変更するものが少ないほど、追跡する必要が少なくなり、結果としてプログラムが単純になります。 (フェデリコ・クヌッセル)

コードをリファクタリングして、array.concat メソッドを使用してミューテーションの問題を解決できます。 array.concat は array.push と同様に機能しますが、元の配列を変更する代わりに、新しい配列を返します。

const addNewComment = (dish: Dish, newComment: Comment) => {
	const editedComments = dish.comments.concat(newComment);
};

お気づきかもしれませんが、このメソッドで新しい comments 配列を作成しますが、返す新しい dish オブジェクトはありません。 これを解決するために、Object.assign グローバル メソッドを使用できます。このメソッドは、プロパティを source オブジェクトから target オブジェクトにコピーし、変更されたターゲット オブジェクトを返します。

最初の引数がターゲットになり、他の引数がソースになります。 この場合、空のオブジェクト {} をターゲットとして使用し、editedComments と dish をソースとして使用します。

import {Dish, Comment} from "./interfaces";
import {pastaDish, pastaComment} from "./pastaDish";

const addNewComment = (dish: Dish, newComment: Comment) => {
	const editedComments = dish.comments.concat(newComment);
	const editedDish = Object.assign({}, dish, {comments: editedComments});
	console.log(editedDish.comments);

	return editedDish;
};

addNewComment(pastaDish, pastaComment);

{} を最初の引数として追加するのを忘れると、editedComments が dish にコピーされ、元の dish オブジェクトが変更されます。

Note
{} を使用して新しいオブジェクトを作成し、editedComments を comments プロパティ内に割り当てて、プロパティの深さと名前を両方のオブジェクトで等しくします。 このようにして、assign メソッドは editedComments を正常にコピーできます。

期待される出力:

[
	{
		rating: 5,
		comment: "Very tasty!",
		author: "Juan Diego",
		date: "04/14/2022",
	},
];

コード例

Spread Operator を使用して、TypeScript でオブジェクトを配列にプッシュする

オブジェクトを配列に追加する別の方法は、ES6 スプレッド演算子を使用することです。 スプレッド演算子は 3つのドット ... で示され、特にオブジェクトまたは配列のプロパティを拡張するために使用できます。

スプレッド演算子を使用して、新しいコメントで新しい配列を作成し、それを dish.comments に割り当てることができます。

import {Dish, Comment} from "./interfaces";
import {pastaDish, pastaComment} from "./pastaDish";

const addNewComment = (dish: Dish, newComment: Comment) => {
	const {comments} = dish;

	dish.comments = [...comments, newComment];
	console.log(dish.comments);
};

addNewComment(pastaDish, pastaComment);

期待される出力:

[
	{
		rating: 5,
		comment: "Very tasty!",
		author: "Juan Diego",
		date: "04/14/2022",
	},
];

まず、オブジェクトの分解 を使用して、dish から comments プロパティにアクセスします。 次に、スプレッド演算子を使用して、newComment を最後の要素として新しい配列の comments 要素を展開し、それを元の dish.comments プロパティに割り当てます。

コード例

オブジェクトを変更せずにスプレッド演算子を使用して、TypeScript でオブジェクトを配列にプッシュする

お気づきかもしれませんが、以前のアプローチで dish の元の値も変更しています。 ただし、編集した comments プロパティを使用して新しい dish オブジェクトを作成して返すことで、これを簡単に修正できます。

幸いなことに、スプレッド演算子をもう一度使用して dish オブジェクトのコピーを作成することで、これを実現できます。

import {Dish, Comment} from "./interfaces";
import {pastaDish, pastaComment} from "./pastaDish";

const addNewComment = (dish: Dish, newComment: Comment) => {
	const {comments} = dish;

	const editedDish = {...dish, comments: [...comments, newComment]};
	console.log(editedDish.comments);

	return editedDish;
};

addNewComment(pastaDish, pastaComment);

期待される出力:

[
	{
		rating: 5,
		comment: "Very tasty!",
		author: "Juan Diego",
		date: "04/14/2022",
	},
];

まず、空の波括弧 {} を使用して新しいオブジェクトを作成します。 次に、スプレッド演算子 ... を使用して新しいオブジェクト内の dish プロパティを展開しますが、新しい comments プロパティを明示的に追加して、新しい値を割り当てることができるようにします。 既存のコメントと newComment の配列。

Note
スプレッド演算子を使用してオブジェクトをコピーすると、料理の 浅いコピー が作成されることを知っておくことが重要です。
{} // New Object
{...dish} // New Dish
{...dish, comments: []} // New Dish With Empty Comments
{...dish, comments: [...comments, newComment]} // New Dish With New Comments

コード例

まとめ

以前のアプローチを使用できます。 ただし、良い慣行と考えられているため、変化しないものを使用することをお勧めします。 一方、ECMAScript 6 で導入されたスプレッド オペレーターを使用すると問題が発生する可能性があるため、古いレガシー ブラウザーでは機能しない可能性があります。

したがって、ブラウザのアクセシビリティが大きな懸念事項である場合は、array.push と array.concat に固執するか、Babel を使用してコードをコンパイルしてください。

参考文献

  1. Mozilla ドキュメンテーション ネットワーク。 (N.D) Array.prototype.push() - JavaScript | MDN。 2022 年 4 月 14 日に https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push から取得
  2. クニュッセル F. (2017). 配列、オブジェクト、ミューテーション。 2022 年 4 月 14 日、https://medium.com/@fknussel/arrays-objects-and-mutations-6b23348b54aa から取得
  3. Mozilla ドキュメンテーション ネットワーク。 (N.D) Array.prototype.concat() - JavaScript | MDN。 2022 年 4 月 14 日に https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat から取得
  4. Mozilla ドキュメンテーション ネットワーク。 (N.D) Array.prototype.assign() - JavaScript | MDN。 2022 年 4 月 14 日に https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign から取得
  5. Mozilla ドキュメンテーション ネットワーク。 (N.D) 拡散構文 (…) - JavaScript | MDN。 2022 年 4 月 14 日に https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax から取得