TypeScript
On this page本页内容
Overview概述Features功能Type Parameters that Extend Document扩展文档的类型参数Type Parameters of Any Type任何类型的类型参数Type Safety and Dot Notation类型安全和点符号Working with the _id Field使用_id
字段Insert Operations and the _id Field插入操作和_id
字段Find Methods and the _id Field查找方法和_id
字段Known Limitations已知限制Recursive Types and Dot Notation递归类型与点表示法Mutual Recursion相互递归
Overview概述
In this guide, you can learn about the TypeScript features and limitations of the MongoDB Node.js driver. 在本指南中,您可以了解MongoDB Node.js驱动程序的TypeScript功能和限制。TypeScript is a strongly typed programming language that compiles to JavaScript.TypeScript是一种可编译为JavaScript的强类型编程语言。
The TypeScript compiler offers type checking in real time. TypeScript编译器提供实时的类型检查。Code editors that support TypeScript can provide autocomplete suggestions, display documentation inline, and identify type-related errors.支持TypeScript的代码编辑器可以提供自动完成建议、内联显示文档以及识别与类型相关的错误。
All TypeScript features of the driver are optional. 驱动程序的所有TypeScript功能都是可选的。All valid JavaScript code written with the driver is also valid TypeScript code.所有使用驱动程序编写的有效JavaScript代码也是有效的TypeScript代码。
For more information, see the TypeScript website.有关更多信息,请参阅TypeScript网站。
Features功能
If you use TypeScript, you can specify a type for some classes in the driver. 如果使用TypeScript,则可以为驱动程序中的某些类指定类型。All classes that accept a type parameter in the driver have the default type 所有在驱动程序中接受类型参数的类都具有默认类型Document
. Document
。The Document
interface has the following definition:Document
接口具有以下定义:
interface Document {
[key: string]: any;
}
All object types extend the 所有对象类型都扩展了Document
interface.Document
接口。
For more information on object types, see the TypeScript handbook.有关对象类型的更多信息,请参阅TypeScript手册。
Type Parameters that Extend Document扩展文档的类型参数
The following classes accept all types that extend the 以下类接受扩展Document
interface:Document
接口的所有类型:
You can pass a type parameter that extends the 您可以传递一个扩展Document
interface like this:Document
接口的类型参数,如下所示:
interface Pet {
name: string;
age: number;
}
const database = client.db("<your database>");
const collection = database.collection<Pet>("<your collection>");
Keys Not in Type Parameter Receive any Type不在类型参数中的键接收任何类型
Keys not listed in your specified type parameter receive the 指定类型参数中未列出的键将接收any
type. any
类型。The following code snippet demonstrates this behavior:以下代码片段演示了这种行为:
interface User {
email: string;
}
const database = client.db("<your database>");
const myColl = db.collection<User>("<your collection>");
myColl.find({ age: "Accepts any type!" });
Type Parameters of Any Type任何类型的类型参数
The following classes accept all type parameters:以下类接受所有类型参数:
You can find a code snippet that shows how to specify a type for the 您可以在查找多个文档用法示例中找到一个代码片段,该代码片段显示如何为FindCursor
class in the Find Multiple Documents Usage Example.FindCursor
类指定类型。
Type Safety and Dot Notation类型安全和点符号
Starting in version 5.0, by default, the Node.js driver does not provide type safety for operations that search on fields expressed in dot notation. 默认情况下,从版本5.0开始,Node.js驱动程序不会为搜索以句点表示的字段的操作提供类型安全性。Dot notation is a syntax you can use to navigate nested JSON objects. When you construct a filter to pass to a query, the driver will not raise a type error even if you specify an incorrectly typed value for a field expressed in dot notation.点表示法是一种可以用于导航嵌套JSON对象的语法。当您构造要传递给查询的筛选器时,即使您为以句点表示的字段指定了类型不正确的值,驱动程序也不会引发类型错误。
The following code snippet defines the 以下代码片段定义了ClassificationPet
interface, which includes a classification
field that enables you to specify the genus and color of dogs and cats:ClassificationPet
界面,其中包括一个classification
字段,用于指定狗和猫的属和颜色:
interface ClassificationPet {
name: string;
age: number;
classification: { genus: "Canis" | "Felis"; color: string };
}
The driver does not raise a type error for the following code sample, even though the value of 驱动程序不会引发以下代码示例的类型错误,即使classification.color
is a boolean instead of a string:classification.color
的值是布尔值而不是字符串:
await myColl.findOneAndDelete({ "classification.color": false });
You can enable type-checking by constructing filters as 您可以通过将筛选器构造为StrictFilter
or StrictUpdateFilter
types.StrictFilter
或StrictUpdateFilter
类型来启用类型检查。
The StrictFilter
and StrictUpdateFilter
types are experimental and may show type errors in valid queries where there should be none.StrictFilter
和StrictUpdateFilter
类型是实验性的,可能会在有效查询中显示类型错误,而这些查询不应该有类型错误。
In the following code sample, the filter is assigned a 在下面的代码示例中,为筛选器分配了StrictFilter
type. StrictFilter
类型。Given this filter type, the Node.js driver reports a type error because the value of 给定这个筛选器类型,Node.js驱动程序会报告一个类型错误,因为classification.color
is a boolean instead of a string.classification.color
的值是布尔值而不是字符串。
const filterPredicate: StrictFilter<ClassificationPet> = { "classification.color": false };
await myColl.findOneAndDelete(filterPredicate);
The following example assigns a 以下示例将StrictUpdateFilter
type to an update filter. StrictUpdateFilter
类型分配给更新筛选器。The Node.js driver reports a type error because the value of Node.js驱动程序报告了一个类型错误,因为classification.color
is a boolean instead of a string.classification.color
的值是布尔值而不是字符串。
const updateFilter: StrictUpdateFilter<ClassificationPet> = { $set: { "classification.color": false } }
await pets.updateOne({}, updateFilter);
Referencing Keys that Incorporate Variables引用包含变量的键
If you need to query a collection or perform another operation with a key that incorporates variables, you must use an 如果需要查询集合或使用包含变量的键执行其他操作,则在指定键时必须使用as const
assertion when specifying the key. as const
断言。This mechanism allows your code to compile successfully as long as the input types are correct.只要输入类型正确,这种机制就允许代码成功编译。
The following code snippet defines the 以下代码片段定义ClassificationPet
interface and the Mealtime
interface. ClassificationPet
接口和Mealtime
接口。ClassificationPet
includes a mealtimes
field that contains an array of Mealtime
interfaces, each of which includes a time
field:ClassificationPet
包括一个mealtimes
字段,该字段包含一组mealtimes
接口,每个接口都包括一个time
字段:
interface ClassificationPet {
name: string;
mealtimes: Mealtime[];
}
interface Mealtime{
time: string;
amount: number;
}
The following code snippet performs a find-and-update operation on a collection of 以下代码片段对ClassificationPet
documents. ClassificationPet
文档的集合执行查找和更新操作。The operation updates the nested 该操作将更新索引time
field of the Mealtime
instance at index 1
. 1
处Mealtime
实例的嵌套time
字段。The index position is specified by the variable 索引位置由变量mealCounter
:mealCounter
指定:
const mealCounter = 1;
await myColl.findOneAndUpdate(
{ name: "Lassie" },
{ $set: { [`mealtimes.${mealCounter}.time` as const]: '4:00 PM' } },
);
To learn more about dot notation, see Dot Notation in the MongoDB manual.要了解更多关于点符号的信息,请参阅MongoDB手册中的点符号。
To learn more about the limitations of dot notation in the Node.js driver, see the Recursive Types and Dot Notation section.要了解更多关于Node.js驱动程序中点符号的限制,请参阅递归类型和点符号部分。
Working with the _id Field使用_id
字段
MongoDB does not recommend specifying the MongoDB不建议将_id
as a part of your model. _id
指定为模型的一部分。Omitting the 省略_id
field makes the model more generic and reusable and more accurately models the data important to an application. _id
字段可以使模型更加通用和可重用,并更准确地对应用程序重要的数据进行建模。The Node driver’s TypeScript integration takes care of adding the Node驱动程序的TypeScript集成负责将_id
field to the return types for relevant methods._id
字段添加到相关方法的返回类型中。
If you need to work with the 如果您需要在模型中使用_id
field in your models, see the below sections for information on write and read operations._id
字段,请参阅以下部分以获取有关写和读操作的信息。
Insert Operations and the _id Field插入操作和_id
字段
How you specify the 在传递给_id
field in type parameters passed to your Collection
instance affects the behavior of insert operations. Collection
实例的类型参数中指定_id
字段的方式会影响插入操作的行为。The following table describes how different 下表描述了不同的_id
field specifications affect insert operations:_id
字段规范如何影响插入操作:
_id field type | |||
---|---|---|---|
No | |||
{ _id: number }; | Yes | _id field in an insert operation, the driver raises an error._id 字段指定值,则驱动程序将引发错误。 | |
{ _id?: number }; | No | _id field in an insert operation, the driver adds an _id field value generated by the primary key factory._id 字段,则驱动程序会添加主键工厂生成的_id 字段值。 |
If you must specify the 如果必须根据需要在定义的类型中指定_id
field as required in the type you define to represent documents in your collection but you do not want to specify values for the _id
field in insert operations, use the OptionalId
helper type when you create your collection. _id
字段以表示集合中的文档,但不希望在插入操作中为_id
字段指定值,请在创建集合时使用OptionalId
帮助器类型。The OptionalId
type accepts a type parameter as an argument and returns that type with an optional _id
field.OptionalId
类型接受一个类型参数作为参数,并使用可选的_id
字段返回该类型。
The following code snippet defines the 以下代码片段定义了IdPet
interface, which includes a type for the _id
field:IdPet
接口,其中包括_id
字段的类型:
interface IdPet {
_id: ObjectId;
name: string;
age: number;
}
The following code uses the preceding interface along with the 以下代码使用前面的接口和OptionalId
type to insert a document without specifying a value for the _id
field:OptionalId
类型插入文档,而不指定_id
字段的值:
const database = client.db("<your database>");
const collection = db.collection<OptionalId<IdPet>>("<your collection>");
myColl.insertOne({
name: "Spot",
age: 2
});
To learn more about the 要了解有关_id
field, see The _id Field in the MongoDB manual._id
字段的更多信息,请参阅MongoDB手册中的_id
字段。
To learn more about the types, interfaces, and classes discussed in this section, see the following resources:要了解本节中讨论的类型、接口和类的更多信息,请参阅以下资源:
- OptionalId
API documentationAPI文件 - PkFactory
API documentationAPI文件 - ObjectId
source code源代码
Find Methods and the _id Field查找方法和_id
字段
The find
and findOne
methods of the Collection
class include the _id
field in their return type. Collection
类的find
和findOne
方法在其返回类型中包含_id
字段。The driver infers the type of the returned 驱动程序根据传递给_id
field based on the type parameter you passed to your Collection
instance.Collection
实例的类型参数推断返回的_id
字段的类型。
If the type parameter you passed to your 如果传递给Collection
instance includes the _id
field in its schema, the driver infers that the _id
field returned from the method is of the type specified in the schema.Collection
实例的类型参数在其架构中包含_id
字段,则驱动程序推断从方法返回的_id
字段属于架构中指定的类型。
However, if the type parameter you passed to your 但是,如果传递给Collection
instance does not include the _id
field in its schema, the driver infers that the type of the _id
field returned from the method is ObjectId
.Collection
实例的类型参数在其架构中不包括_id
字段,则驱动程序推断从该方法返回的_id
字段的类型为ObjectId
。
The type parameter passed to your 传递给Collection
influences only the type inference of the fields returned from the method. Collection
的类型参数只影响从方法返回的字段的类型推断。The driver does not convert the field to the specified type. 驱动程序未将字段转换为指定的类型。The type of each field in your type parameter's schema should match the type of the corresponding field in the collection.类型参数架构中每个字段的类型都应与集合中相应字段的类型相匹配。
The following code uses the Pet interface to return a document with an 以下代码使用_id
inferred to be of type ObjectId
:Pet
接口返回一个_id
被推断为ObjectId
类型的文档:
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;
The following code uses the 以下代码使用IdNumberPet
interface to return a document with an _id
inferred to be of type number
:IdNumber
Pet接口返回一个_id
被推断为number
类型的文档:
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;
Projection投影
If you specify a projection in a find method, you should pass a type parameter to your find method that reflects the structure of your projected documents. 如果在查找方法中指定投影,则应向查找方法传递反映投影文档结构的类型参数。Without a type parameter, TypeScript cannot check at compile time that you are using your projected documents safely.如果没有类型参数,TypeScript就无法在编译时检查您是否安全地使用了投影文档。
To show this behavior, the following code snippet passes type checking but raises an error at runtime:为了显示这种行为,以下代码片段通过了类型检查,但在运行时引发了错误:
const doc = await myColl.findOne(
{},
{ projection: { _id: 0, name: 1 } }
);
console.log(doc._id.generationTime);
To catch this error at compile time, pass a type parameter that does not include the 要在编译时捕获此错误,请将不包括_id
field to your find method:_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);
To view a runnable TypeScript example that includes a find method applying a projection, see the Find a Document page.要查看包含应用投影的查找方法的可运行TypeScript示例,请参阅查找文档页面。
To learn more about the classes and methods discussed in this section, see the following API documentation:要了解有关本节中讨论的类和方法的更多信息,请参阅以下API文档:
Known Limitations已知限制
Learn about the following TypeScript specific limitations of the Node.js driver:了解Node.js驱动程序的以下TypeScript特定限制:
No type safety for dot notation references to nested instances of recursive types对递归类型的嵌套实例的点表示法引用没有类型安全性Depth limitations on type safety for mutually recursive types相互递归类型的类型安全深度限制
Recursive Types and Dot Notation递归类型与点表示法
The Node.js driver cannot provide type safety within nested instances of recursive types referenced through dot notation.Node.js驱动程序无法在通过点表示法引用的递归类型的嵌套实例中提供类型安全性。
A recursive type is a type that references itself. 递归类型是一种引用自身的类型。You can update the Pet interface to be recursive by allowing a pet to have its own pet. The following is the recursive 您可以通过允许宠物拥有自己的宠物来更新宠物界面,使其递归。以下是递归Pet
interface:Pet
接口:
interface RecursivePet {
pet?: RecursivePet;
name: string;
age: number;
}
Depth Limit深度限制
The Node.js driver does not traverse nested recursive types when type checking dot notation keys to avoid hitting TypeScript's recursive depth limit.Node.js驱动程序在类型检查点符号键时不遍历嵌套的递归类型,以避免达到TypeScript的递归深度限制。
The following code snippet references a nested instance of the RecursivePet interface with an incorrect type using dot notation, but the TypeScript compiler does not raise a type error:以下代码段使用点表示法引用了具有不正确类型的RecursivePet接口的嵌套实例,但TypeScript编译器不会引发类型错误:
database
.collection<RecursivePet>("<your collection>")
.findOne({ "pet.age": "Spot" });
The following code snippet references a top-level instance of the 以下代码段引用了具有不正确类型的RecursivePet
interface with an incorrect type and raises a type error:RecursivePet
接口的顶级实例,并引发类型错误:
database
.collection<RecursivePet>("<your collection>")
.findOne({ pet: "Spot" });
The error raised by the preceding code snippet is as follows:前面的代码段引发的错误如下:
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>'.
If you must have type safety within nested instances of recursive types, you must write your query or update without dot notation.如果必须在递归类型的嵌套实例中具有类型安全性,则必须在不使用句点表示法的情况下编写查询或更新。
To learn more about dot notation, see Dot Notation in the MongoDB manual.要了解更多关于点符号的信息,请参阅MongoDB手册中的点符号。
Mutual Recursion相互递归
A mutually recursive type exists when two types contain a property that is of the other's type. 当两个类型包含属于另一个类型的属性时,就存在相互递归的类型。You can update the Pet interface to be mutually recursive by allowing a pet to have a handler, and defining a handler to have a pet. 您可以通过允许宠物拥有一个处理程序,并定义一个处理者来拥有宠物,从而将Pet接口更新为相互递归。The following examples reference the mutually recursive 以下示例引用了相互递归的Pet
and Handler
interfaces:Pet
和Handler
接口:
interface Pet {
handler?: Handler;
name: string;
age: number;
}
interface Handler {
pet: Pet;
name: string;
}
The Node.js driver provides type safety for mutually recursive types referenced through dot notation up to a depth of eight. Node.js驱动程序为通过点符号引用的相互递归类型提供类型安全性,深度可达8。The following code snippet assigns a 以下代码段将string
to a number
and raises a type error because the referenced property is at a depth of four:string
分配给一个number
,并引发类型错误,因为引用的属性深度为4:
database
.collection<Pet>("<your collection>")
.findOne({'handler.pet.handler.pet.age': "four"});
The error raised by the preceding code snippet is as follows:前面的代码段引发的错误如下:
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'.
At a depth greater than or equal to eight, TypeScript compiles your code but no longer type checks it. 在大于或等于8的深度处,TypeScript编译代码,但不再对其进行类型检查。The following code assigns a 以下代码将string
to a number
property but does not cause a compilation error because the referenced property is at a depth of 10:string
分配给number
属性,但不会导致编译错误,因为引用的属性深度为10:
database
.collection<Pet>("<your collection>")
.findOne({'handler.pet.handler.pet.handler.pet.handler.pet.handler.pet.age': "four"});