RawObjectDataProcessor — 最少理論
RawObjectDataProcessorを利用する際は、 JavaScript・TypeScript、 正確にはECMAScript規格考慮する必要が有る。 これらの注意点は当然、公式・非公式のリソースでドキュメント化されているが、多数の初心者プログラマーはそれらを知らない事も多い。
オブジェクト系データ分類化
「RawObjectDataProcessor」という名前の直訳から分かる通り、此のユーティリティクラスは オブジェクト型データ、つまりtypeof N === "object"という条件を満たした上で、 かつnullではないデータを扱う為のものである。 ところで、ECMAScript規格の観点では、 typeof nullも"object"となっている。 子プロパティなら、数型や文字列や真偽を含めて他の型を持つ事が出来る。 但し、現時点ではJSON互換のデータのみが 完全にサポートされている。 該当している型の定義は以下の通り。
export type ParsedJSON = ParsedJSON_Object | ParsedJSON_Array;
export type ParsedJSON_Object = { [key: string]: ParsedJSON_NestedProperty; };
export type ParsedJSON_Array = Array<ParsedJSON_NestedProperty>;
export type ParsedJSON_NestedProperty =
number |
string |
boolean |
null |
ParsedJSON_Object |
ParsedJSON_Array |
undefined;
「オブジェクト」や「配列」といった用語はJSONに対してもよく使われるが、 JSONはオブジェクトではなく文字列である 事を意識しておく必要が有る。 其の為、上記のエイリアス名は、単なるJSON_Objectや JSON_Arrayではなく、「parsed」(「処理済み」)単語 で始まっている。
ECMAScript系言語の場合、JSON文字列から通常のオブジェクトを取得するには、 一般的にJSON.parse()が使用される。 「JavaScript Object Notation」という復号から分かる通り、JSON形式は JavaScriptに由来しているが、他の多くの人気なプログラミング言語でも此のデータ形式が扱われており、 そこではJSON文字列は各言語がサポートするデータ型に変換される。
将来的に、DateやBigIntの様な他の型の 子プロパティのサポートが追加される可能性は有る。 然し現時点では、外部ソースからデータを読み込んでJavaScriptオブジェクトに変換する場合、それらは通常 JSON互換であり、DateやBigInt 型のプロパティが必要な場合は後処理で文字列から変換出来る為、此の機能の需要はそれほど高くない。
さて、RawObjectDataProcessorは以下の4つのオブジェクトの サブタイプを扱っている。
| ↓ キーの型 / ➝ 要素数 | 固定 | 任意 |
|---|---|---|
| 文字列 | 固定構造オブジェクト | 連想配列 |
| 非負整数 | タプル | インデックス配列 |
固定構成のオブジェクト
これらのオブジェクト・サブタイプでは、あり得る全ての プロパティ名が予め判明している事が前提となる。デモで使用されているSampleType型は、此の様なオブジェクト・サブタイプの例である。
type SampleType = {
foo: number;
bar: string;
baz: boolean;
hoge?: number;
fuga: string | null;
quux: {
alpha: number;
bravo: "PLATINUM" | "GOLD" | "SILVER";
};
};
固定構造である事は、多態的な(ポリモフィックな)プロパティを禁止するものではないが、 以下の例の様に、あり得る選択肢が予め分かっている必要がある。
type SampleTypeWithPolymopthocProperties = {
foo:
{ hoge: string; } |
{ fuga: number: }
bar: number:
baz: string;
};
此の型のオブジェクトは、最も一般的である。 クライアントとサーバー間等で送受信されるシリアライズされたデータは、殆どの場合此の形式。 JSONやYAML形式等のファイルに保存される設定も、通常はこの形式である (例えばTypeScriptの設定ファイルのtsconfig.json)。
連想配列型のオブジェクト
連想配列は、固定構造オブジェクトとは異なり、プロパティ名が事前に 分かっておらず、要素数も0から最大整数範囲内ならいくらでも有り得る。
ESMAScript 2015規格以前は、此の様な配列として 通常のオブジェクトが使用されていた。 出力JavaScriptコードの観点では、固定構造オブジェクトと何ら 変わりない。 TypeScriptでは、こうした連想配列は以下の何れかのの方法で アノテーションされる。
type AssociativeArray<ValueType> = { [ key: string ]: ValueType };
// 又は
type AssociativeArray<ValueType> = Record<string, ValueType>;
ESMAScript 2015規格で導入されたMap データ型を連想配列と呼ぶかどうかは、其の配列が何れでもの型の キーを許容するかどうかに依存する。 特にMapはオブジェクト型のキーを禁止していない。 何れにせよ、Map型はJSONと互換性がない。 然し、Mapを二次元のインデックス配列に変換する事で、互換性を持たせる事が出来る。 此の場合、各子配列の1番目の 要素をキー、2番目の要素を値とする。
const sampleMap: Map<string, number> = new Map([
[ "alpha", 1 ],
[ "bravo", 2 ],
[ "charlie", 3 ]
]);
const serializedMap: string = JSON.stringify(Array.from(sampleMap.entries()));
頻繁に使用される連想配列の他の例として、package.jsonの多くのフィールド (scripts、dependencies、 devDependencies、 peerDependencies等)が挙げられる。
RawObjectDataProcessorは当然、文字列のキーを持つ 通常の連想配列をサポートしているが、JSONとの互換性が無い為、 Map型の入力データはサポートしていない。 但し、後処理機能を利用する事で、目的のデータをMapに変換する事は可能である。
指数配列
要素の順番が不可欠であり、各要素への アクセスがインデックスという0から始まる整数 に行わるコレクションの一種類である。 日本語でも英語でも、単に「配列」(array(s))と言う場合、連想配列では なくインデックス配列を指す事が多い。
多くの静的型付け言語(例えばC++、C#、Java)では、 通常のインデックス配列は要素数が 固定されており、多くの場合、要素の型も 統一されている。 要素の追加や削除が必要な場合は、専用のコレクションが使用される。 これ等は概念的には同じインデックス配列だが、内部で標準的な配列 を別のものに差し替える事に依り要素の追加・削除を可能にしている。
ECMAScriptに関しては、インデックス配列はArrayというクラス の様なオブジェクトのインスタンスである (X instanceof Arrayは真)。 こうしたインデックス配列は柔軟に操作出来る(具体的には、全く異なる型の要素を指定したり、 要素を追加・削除したり出来る)、今のところ追加のコレクションの必要性はない。
TypeScriptでインデックス配列をアノテーションするには、以下の何れかの方法がある。
const indexedArray: string[] = [ "Alpha", "Bravo" ];
// または
const indexedArray: Array<string> = [ "Alpha", "Bravo" ];
固定構造オブジェクトと同様に、インデックス配列は最も一般的なデータ型の一つであり、 至る所で広く使われている。 固定構造オブジェクトや連想配列とは異なり、インデックス配列は要素の順序を 保証する為、順番の考慮が不可欠な場合、変わりの無いものになっている。
タプル
概念的には、タプルとは要素数が固定された# [+Term__Contrast--YDID 配列](一般的にはインデックス配列に限らない)のものである。
ECMAScript 2025規格(前述のECMAScript 2015と混同しない事) 以前は、JavaScriptに要素数を制限した配列 作成専用の機能は無かった。 TypeScriptでは、「タプル」(「tuple」)という用語は、 以下のようにアノテーションされるインデックス配列のみに適用されていた。
const tupleOfTwoElements: [ string, number ] = [ "ALPHA", 1 ];
const tupleOfThreeElements: [ string, number, boolean ] = [ "BRAVO", 2, true ];
ECMAScript 2025規格では、新しいタプル型が登場した。 此れは要素数が固定されている事に加え、初期化後は読み取り専用と成る。 それで不変性を保証する為に、ArrayやMapや Set等を含めて、如何なるオブジェクトのサブタイプが 禁じてある。 此のデータ型は未だ非常に新しい為、様々な環境で広くサポートされる迄には時間がかかるだろう。 又、其の制限の為広く普及しない事も予想され、当然ながらRawObjectDataProcessorは此のデータ型を サポートしていない。 其の為、以降は既にRawObjectDataProcessorと互換性がある TypeScriptのタプルについて述べる。
タプルはそれほど一般的ではないが、使用例はある。 例えば、ReactのuseState関数は、2つの要素からなる タプルを返す。 全てではないが、多くのESLintルールの設定も、2番目の要素が 任意ではあるが、強いて言えば「タプル」と呼ぶ事が出来る。 何れにせよ、2つの位置それぞれに特定の型の要素が期待されており、 此れがタプルの主な特徴である。