Docs Menu
Docs Home
/ / /
Node.js
/

TypeScript

項目一覧

  • Overview
  • 主な機能
  • ドキュメントを拡張する型パラメーター
  • 任意の型パラメーター
  • 型の安全性とドット表記
  • _id フィールドとの連携
  • 挿入操作と _id フィールド
  • メソッドと _id フィールドの検索
  • 既知の制限
  • 再帰型とドット表記
  • 相互再帰

このガイドでは、MongoDB Node.js ドライバーの TypeScript 機能と制限について学習できます。TypeScript は、JavaScript にコンパイルされる、厳密に型指定されたプログラミング言語です。

TypeScript コンパイラーはリアルタイムで型をチェックします。TypeScript をサポートするコード エディターは、オートコンプリートの提案を提供したり、ドキュメントをインラインで表示したり、型関連のエラーを識別したりできます。

ドライバーのすべての TypeScript 機能は任意です。ドライバーを使用して記述されたすべての有効な JavaScript コードは、有効な TypeScript コードでもあります。

詳細については、Typescript のウェブサイトを参照してください。

TypeScript を使用する場合は、ドライバー内の一部のクラスの型を指定できます。ドライバー内の型パラメーターを受け入れるすべてのクラスのデフォルトの型は Document です。Document インターフェースには、次の定義があります。

interface Document {
[key: string]: any;
}

すべてのオブジェクト型は Document インターフェースを拡張します。

オブジェクトタイプの詳細については、Typescript を参照してください。

次のクラスは、Document インターフェースを拡張するすべての型を受け入れます。

次のように、Document インターフェースを拡張する型パラメーターを渡すことができます。

1interface Pet {
2 name: string;
3 age: number;
4}
5
6const database = client.db("<your database>");
7const collection = database.collection<Pet>("<your collection>");

重要

型パラメーターにないキーは任意の型を受け取ります

指定した型パラメーターにリストされていないキーは、any 型を受け取ります。次のコード スニペットは、この動作を示しています。

1interface User {
2 email: string;
3}
4
5const database = client.db("<your database>");
6const myColl = db.collection<User>("<your collection>");
7myColl.find({ age: "Accepts any type!" });

次のクラスは、すべての型パラメーターを受け入れます。

FindCursorクラスの型を指定する方法を示すコード スニペットは、 複数のドキュメントの検索の使用例に記載されています。

バージョン 5.0 以降、Node.js ドライバーは、デフォルトで、ドット表記で表現されたフィールドを検索する操作に対して型の安全性を提供しません。ドット表記は、ネストされた JSON オブジェクトをナビゲートするために使用できる構文です。クエリに渡すフィルターを作成する場合、ドット表記で表現されたフィールドに誤った型の値を指定しても、ドライバーは型エラーを生成しません。

次のコード スニペットは、犬と猫の属と色を指定できる classification フィールドを含む ClassificationPet インターフェースを定義します。

interface ClassificationPet {
name: string;
age: number;
classification: { genus: "Canis" | "Felis"; color: string };
}

次のコード サンプルでは、classification.color の値が文字列ではなくブール値であるにもかかわらず、ドライバーは型エラーを生成しません。

await myColl.findOneAndDelete({ "classification.color": false });

フィルターを StrictFilter または StrictUpdateFilter 型として構築することで、型チェックを有効にすることができます。

警告

StrictFilterStrictUpdateFilter型は実験的なものであり、有効なクエリでは型エラーが発生しないはずです。

次のコード サンプルでは、フィルターに StrictFilter 型が割り当てられています。このフィルター型の場合、classification.color の値が文字列 ではなくブール値であるため、Node.js ドライバーは型エラーを報告します。

const filterPredicate: StrictFilter<ClassificationPet> = { "classification.color": false };
await myColl.findOneAndDelete(filterPredicate);

次の例では、アップデート フィルターに StrictUpdateFilter 型を割り当てます。Node.js ドライバーは、 classification.colorの値が文字列ではなくブール値であるため、型エラーを報告します。

const updateFilter: StrictUpdateFilter<ClassificationPet> = { $set: { "classification.color": false } }
await pets.updateOne({}, updateFilter);

コレクションをクエリしたり、変数を組み込んだキーを使用して別の操作を実行したりするには、キーを指定するときに as const アサーションを使用する必要があります。このメカニズムにより、入力型が正しい場合にコードを正常にコンパイルできます。

次のコード スニペットは、ClassificationPet インターフェースと Mealtime インターフェースを定義します。ClassificationPet には、Mealtime インターフェースの配列を含む mealtimes フィールドが含まれており、各インターフェースには time フィールドが含まれています。

interface ClassificationPet {
name: string;
mealtimes: Mealtime[];
}
interface Mealtime{
time: string;
amount: number;
}

次のコード スニペットは、ClassificationPet ドキュメントのコレクションに対して検索とアップデートの操作を実行します。この操作は、インデックス 1 にある Mealtime インスタンスのネストされた time フィールドをアップデートします。インデックス位置は変数mealCounterによって指定されます。

const mealCounter = 1;
await myColl.findOneAndUpdate(
{ name: "Lassie" },
{ $set: { [`mealtimes.${mealCounter}.time` as const]: '4:00 PM' } },
);

ドット表記の詳細については、MongoDB マニュアルの「ドット表記 」を参照してください。

Node.js ドライバーのドット表記の制限の詳細については、「再帰型とドット表記 」セクションを参照してください。

MongoDB では、モデルの一部として _id を指定することは推奨されません。_id フィールドを省略すると、モデルはより汎用的かつ再利用可能になり、アプリケーションにとって重要なデータをより正確にモデル化します。Node ドライバーの TypeScript 統合により、関連するメソッドの戻り値の型に _id フィールドが追加されます。

次のセクションでは、_id フィールドを使用する書込み操作と読み取り操作について説明します。

Collection インスタンスに渡される型パラメーターで _id フィールドをどのように指定するかは、挿入操作の動作に影響します。次の表は、さまざまな _id フィールドの仕様が挿入操作にどのように影響するかを示しています。

_id フィールド型
例型
挿入時に必要
挿入時の動作
Unspecified
Not applicable
No
The driver creates an ObjectId value for each inserted document.
Specified
{ _id: number };
Yes
If you do not specify a value for the _id field in an insert operation, the driver raises an error.
Specified as optional
{ _id?: number };
No
If you do not specify the _id field in an insert operation, the driver adds an _id field value generated by the primary key factory.

コレクション内のドキュメントを表すために定義する型で必須として _id フィールドを指定する必要があり、挿入操作で _id フィールドの値を指定したくない場合は、コレクションを作成するときに OptionalId ヘルパー型を使用します。OptionalId 型は、型パラメータを引数として受け入れ、任意の _id フィールドとともにその型を返します。

次のコード スニペットは、_id フィールドの型を含む IdPet インターフェースを定義します。

interface IdPet {
_id: ObjectId;
name: string;
age: number;
}

次のコードでは、前述のインターフェースとOptionalId型を使用して、 _idフィールドに値を指定せずにドキュメントを挿入します。

const database = client.db("<your database>");
const collection = db.collection<OptionalId<IdPet>>("<your collection>");
myColl.insertOne({
name: "Spot",
age: 2
});

_idフィールドの詳細については、MongoDB マニュアルの「 _id フィールド」を参照してください。

このセクションで説明した型、インターフェース、クラスの詳細については、次のリソースを参照してください。

Collection クラスの find メソッドと findOne メソッドには、戻り値の型に _id フィールドが含まれます。ドライバーは、Collection インスタンスに渡した型パラメーターに基づいて、返される _id フィールドの型を推測します。

Collection インスタンスに渡した型パラメーターのスキーマに _id フィールドが含まれている場合、ドライバーはメソッドから返された _id フィールドがスキーマで指定された型であると推測します。

ただし、Collection インスタンスに渡した型パラメーターのスキーマに _id フィールドが含まれていない場合、ドライバーはメソッドから返される _id フィールドの型が ObjectId であると推測します。

Tip

Collectionに渡される型パラメータは、メソッドから返されるフィールドの型推論にのみ影響します。 ドライバーは、指定された型にフィールドを変換しません。 型パラメータのスキーマ内の各フィールドの型は、コレクション内の対応するフィールドの型と一致する必要があります。

次のコードは、 Pentインターフェースを使用して、 _idObjectId型であると推測されるドキュメントを返します。

const database = client.db("<your database>");
const collection = db.collection<Pet>("<your collection>");
const document = await myColl.findOne({
name: "Spot",
});
const id : ObjectId = document._id;

次のコードは、IdNumberPet インターフェースを使用して、_idnumber 型であると推測されるドキュメントを返します。

interface IdNumberPet {
_id: number;
name: string;
age: number;
}
const database = client.db("<your database>");
const collection = db.collection<IdNumberPet>("<your collection>");
const document = await myColl.findOne({
name: "Spot",
});
const id : number = document._id;

重要

プロジェクション

find メソッドでプロジェクションを指定する場合は、プロジェクションされるドキュメントの構造を反映する型パラメーターを find メソッドに渡す必要があります。 型パラメータがないと、 Typescriptはコンパイル時にプロジェクションされたドキュメントが安全に使用されているかどうかを確認できません。

この動作を示すために、次のコード スニペットは型のチェックに合格しますが、実行時にエラーが発生します。

const doc = await myColl.findOne(
{},
{ projection: { _id: 0, name: 1 } }
);
console.log(doc._id.generationTime);

コンパイル時にこのエラーをキャッチするには、_id フィールドを含まない型パラメーターを find メソッドに渡します。

interface ProjectedDocument {
name: string
}
const doc = await myColl.findOne<ProjectedDocument>(
{},
{ projection: { _id: 0, name: 1 } }
);
// Compile time error: Property '_id' does not exist on type 'ProjectedDocument'.
console.log(doc._id.generationTime);

プロジェクションを適用する find メソッドを含む実行可能な TypeScript の例を表示するには、「ドキュメントの検索」ページを参照してください。

このセクションで説明するクラスとメソッドについて詳しくは、次の API ドキュメントを参照してください。

Node.js ドライバーの次の TypeScript 固有の制限について説明します。

Node.js ドライバーは、ドット表記で参照される再帰型のネストされたインスタンス内で型の安全性を確保できません。

再帰型とは、自分自身を参照する型です。 ポッドが独自のプライベートを持つことを許可することで、 Petインターフェースを再帰的に更新できます。 以下は、再帰的なPetインターフェースです。

interface RecursivePet {
pet?: RecursivePet;
name: string;
age: number;
}

注意

深度制限

Node.js ドライバーは、TypeScript の再帰深度制限に達するのを避けるために、ドット表記キーの型チェック時にネストされた再帰型を走査しません。

次のコード スニペットは、ドット表記を使用して間違った型を持つRecursivePatインターフェースのネストされたインスタンスを参照しますが、 Typescriptコンパイラーは型エラーを生成しません。

database
.collection<RecursivePet>("<your collection>")
.findOne({ "pet.age": "Spot" });

次のコード スニペットは、間違った型を持つ RecursivePet インターフェースの最上位インスタンスを参照し、型エラーを発生させます。

database
.collection<RecursivePet>("<your collection>")
.findOne({ pet: "Spot" });

上記のコード スニペットによって発生するエラーは次のとおりです。

index.ts(19,59): error TS2769: No overload matches this call.
The last overload gave the following error.
Type 'string' is not assignable to type 'Condition<Pet>'.

再帰型のネストされたインスタンス内で型の安全性を確保する必要がある場合は、ドット表記を使用せずにクエリまたはアップデートを記述する必要があります。

ドット表記の詳細については、MongoDB マニュアルの「ドット表記 」を参照してください。

相互再帰型は、2 つの型にもう 1 つの型であるプロパティが含まれている場合に存在します。 Perlインターフェースを相互再帰的に更新するには、Perl がハンドラーを持つことを許可し、ペインを含むハンドラーを定義します。 次の例えでは、相互再帰的なPet インターフェースとHandler インターフェースを参照します。

interface Pet {
handler?: Handler;
name: string;
age: number;
}
interface Handler {
pet: Pet;
name: string;
}

Node.js ドライバーは、ドット表記法で参照される相互再帰型に対して、最大「8」の深度までの型の安全性を提供します。次のコード スニペットは、stringnumber に割り当て、参照されるプロパティの深度が「4」であるため、型エラーを発生させます。

database
.collection<Pet>("<your collection>")
.findOne({'handler.pet.handler.pet.age': "four"});

上記のコード スニペットによって発生するエラーは次のとおりです。

index.ts(19,59): error TS2769: No overload matches this call.
The last overload gave the following error.
Type 'string' is not assignable to type 'Condition<number> | undefined'.

深度が「8」以上の場合、TypeScript はコードをコンパイルしますが、型チェックは行いません。次のコードは、stringnumber プロパティに割り当てますが、参照されるプロパティの深度が「10」であるため、コンパイル エラーは発生しません。

database
.collection<Pet>("<your collection>")
.findOne({'handler.pet.handler.pet.handler.pet.handler.pet.handler.pet.age': "four"});

戻る

時系列