Docs Menu
Docs Home
/ / /
Node.js
/

TypeScript

이 페이지의 내용

  • 개요
  • 기능
  • 문서를 확장하는 유형(Type) 매개변수
  • 모든 유형의 유형(Type) 매개변수
  • 유형(Type) 안전 및 점 표기법
  • _id 필드 작업
  • 삽입 작업 및 _id field
  • 찾기 메서드 및 _id 필드
  • 알려진 제한 사항
  • 재귀 유형(Type) 및 점 표기법
  • 상호 재귀

이 가이드에서는 MongoDB Node.js 드라이버 내 TypeScript의 기능 및 제한 사항에 대해 알아볼 수 있습니다. 타입스크립트(Typescript)는 강력하게 유형화된(typed) 프로그래밍 언어로, 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 collection = db.collection<User>("<your collection>");
7collection.find({ age: "Accepts any type!" });

다음 클래스는 모든 유형 매개변수를 허용합니다.

여러 문서 찾기 사용 예시에서 FindCursor 클래스의 유형을 지정하는 방법을 보여주는 코드 스니펫을 찾을 수 있습니다.

점 표기법 으로 쿼리 또는 업데이트를 지정하는 경우 Node.js 드라이버는 쿼리 또는 업데이트가 재귀 유형의 중첩된 인스턴스를 참조 하지 않는 경우 유형 안전성을 제공합니다. 점 표기법은 중첩된 JSON 객체를 탐색하는 데 사용할 수 있는 구문입니다.

다음 코드 스니펫은 ClassificationPet 인터페이스를 정의하며, 여기에는 개와 고양이의 속과 색을 지정할 수 있는 classification 필드가 포함되어 있습니다:

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

다음 코드 스니펫은 쿼리에서 지원되지 않는 동물의 속을 지정할 때 유형 오류를 올바르게 발생시킵니다.

database
.collection<ClassificationPet>("<your collection>")
.find({ "classification.genus": "Sylvilagus" });

앞의 코드 스니펫에서 발생한 유형 오류는 다음과 같습니다.

No overload matches this call.
...
Type '"Sylvilagus"' is not assignable to type 'Condition<"Canis" | "Felis">'.

변수를 포함하는 키로 컬렉션을 쿼리하거나 다른 작업을 수행해야 하는 경우 키를 지정할 때 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 collection.findOneAndUpdate(
{ name: "Lassie" },
{ $set: { [`mealtimes.${mealCounter}.time` as const]: '4:00 PM' } },
);

점 표기법에 대해 자세히 알아보려면 MongoDB 매뉴얼의 점 표기법을 참조하세요.

Node.js 드라이버 내 점 표기법의 제한 사항에 대해 자세히 알아보려면 재귀 유형 및 점 표기법 섹션을 참조하세요.

MongoDB는 _id을(를) 모델의 일부로 지정하는 것을 권장하지 않습니다. _id 필드를 생략하면 모델이 더 일반적이고 재사용 가능하며 애플리케이션에 중요한 데이터를 더 정확하게 모델링할 수 있습니다. 노드 드라이버의 타입스크립트(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.

collection의 문서를 나타내기 위해 정의하는 유형에서는 _id 필드를 필수로 지정해야 합니다. 하지만 삽입 연산에서 _id 필드의 값을 지정하고 싶지 않다면 collection을 생성할 때 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>");
collection.insertOne({
name: "Spot",
age: 2
});

_id 필드에 대해 자세히 알아보려면 MongoDB 매뉴얼의 _id 필드를 참조하세요.

이 섹션에서 설명하는 유형, 인터페이스 및 클래스에 대해 자세히 알아보려면 다음 리소스를 참조하세요.

Collection 클래스의 findfindOne 메서드는 반환 유형에 _id 필드를 포함합니다. 드라이버는 Collection 인스턴스에 전달한 유형 매개변수를 기반으로 반환된 _id 필드의 유형을 유추합니다.

Collection 인스턴스에 전달한 유형 매개변수의 스키마에 _id 필드가 포함된 경우, 드라이버는 메서드에서 반환된 _id 필드가 스키마에 지정된 유형이라고 유추합니다.

하지만 Collection 인스턴스에 전달한 유형 매개변수의 스키마에 _id 필드가 포함되어 있지 않은 경우, 드라이버는 메서드에서 반환된 _id 필드의 유형이 ObjectId라고 유추합니다.

Collection에 전달된 유형 매개변수는 메서드에서 반환된 필드의 유형 추론에만 영향을 미칩니다. 드라이버는 필드를 지정된 형식으로 변환하지 않습니다. 유형 매개변수 스키마의 각 필드 유형은 컬렉션의 해당 필드 유형과 일치해야 합니다.

다음 코드는 인터페이스를 사용하여 ObjectId 유형으로 유추되는 _id가 있는 문서를 반환합니다.

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

다음 코드는 IdNumberPet 인터페이스를 사용하여 _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 collection.findOne({
name: "Spot",
});
const id : number = document._id;

중요

프로젝션

찾기 메서드에서 프로젝션을 지정하는 경우 프로젝션된 문서의 구조를 반영하는 유형 매개변수를 찾기 메서드에 전달해야 합니다. 유형 매개변수가 없으면 TypeScript는 컴파일 타임에 프로젝션된 문서를 안전하게 사용하고 있는지 확인할 수 없습니다.

이 동작을 보여주기 위해 다음 코드 스니펫은 유형 검사를 통과하지만 런타임 시 오류를 발생시킵니다.

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

컴파일 시 이 오류를 포착하려면 _id 필드를 포함하지 않는 유형 매개 변수를 find 메서드에 전달합니다.

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

프로젝션을 적용하는 찾기 메서드가 포함된 실행 가능한 TypeScript 예시를 보려면 문서 찾기 페이지를 참조하세요.

이 섹션에서 설명하는 클래스 및 메서드에 대해 자세히 알아보려면 다음 API 문서를 참조하세요.

Node.js 드라이버의 다음 TypeScript 관련 제한 사항에 대해 알아보세요:

Node.js 드라이버는 점 표기법을 통해 참조되는 재귀 유형의 중첩된 인스턴스 내에서 유형 안전성을 제공할 수 없습니다.

재귀 유형은 자체 리소스를 레퍼런스로 활용하는 유형입니다. 펫이 자기 소유의 펫을 가질 수 있도록 허용하여 인터페이스를 재귀적으로 업데이트할 수 있습니다. 다음은 재귀적 Pet 인터페이스입니다.

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

참고

깊이 제한

Node.js 드라이버는 점 표기법 키를 유형 검사할 때 중첩된 재귀 유형을 트래버스하지 않으므로 TypeScript의 재귀 깊이 제한에 부딪히지 않도록 합니다.

다음 코드 스니펫은 잘못된 유형의 점 표기법을 사용하여 중첩된 RecursivePet 인터페이스의 인스턴스를 레퍼런스로 활용하지만 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 매뉴얼의 점 표기법을 참조하세요.

상호 재귀 유형은 두 유형에 다른 유형의 속성이 포함되어 있을 때 존재합니다. 펫이 핸들러를 가질 수 있도록 허용하고 핸들러가 펫을 가질 수 있도록 정의하여 인터페이스를 상호 재귀적으로 업데이트할 수 있습니다. 다음 예시에서는 상호 재귀적인 PetHandler 인터페이스를 참조합니다.

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는 코드를 컴파일하지만 더 이상 유형 검사를 수행하지 않습니다. 다음 코드에서는 number 속성에 string을 할당하지만 레퍼런스 속성의 깊이가 10이므로 컴파일 오류가 발생하지 않습니다.

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