TypeScript
이 페이지의 내용
개요
이 가이드에서는 MongoDB Node.js 드라이버 내 TypeScript의 기능 및 제한 사항에 대해 알아볼 수 있습니다. 타입스크립트(Typescript)는 강력하게 유형화된(typed) 프로그래밍 언어로, JavaScript로 컴파일됩니다.
TypeScript 컴파일러는 실시간으로 유형 검사를 제공합니다. TypeScript를 지원하는 코드 편집기는 자동 완성 기능을 제공하고, 문서를 인라인으로 표시하고, 유형 관련 오류를 식별할 수 있습니다.
드라이버의 모든 TypeScript 기능은 선택 사항입니다. 드라이버로 작성된 모든 유효한 JavaScript 코드는 유효한 TypeScript 코드이기도 합니다.
자세한 내용은 TypeScript 웹사이트를 참조하세요.
기능
TypeScript를 사용하는 경우 드라이버의 일부 클래스에 대한 유형을 지정할 수 있습니다. 드라이버에서 유형 매개 변수를 허용하는 모든 클래스의 기본 유형은 Document
입니다. Document
인터페이스의 정의는 다음과 같습니다:
interface Document { [key: string]: any; }
모든 객체 유형은 Document
인터페이스를 확장합니다.
객체 유형에 대한 자세한 내용은 TypeScript 핸드북을 참조하세요.
문서를 확장하는 유형(Type) 매개변수
다음 클래스는 Document
인터페이스를 확장하는 모든 유형을 허용합니다.
다음과 같이 Document
인터페이스를 확장하는 유형 매개 변수를 전달할 수 있습니다:
1 interface Pet { 2 name: string; 3 age: number; 4 } 5 6 const database = client.db("<your database>"); 7 const collection = database.collection<Pet>("<your collection>");
중요
유형 매개변수에 없는 키는 모든 유형 수신
지정한 유형 매개 변수에 나열되지 않은 키는 any
유형 수신. 다음 코드 스니펫은 이 동작을 보여줍니다:
1 interface User { 2 email: string; 3 } 4 5 const database = client.db("<your database>"); 6 const myColl = db.collection<User>("<your collection>"); 7 myColl.find({ age: "Accepts any type!" });
모든 유형의 유형(Type) 매개변수
다음 클래스는 모든 유형 매개변수를 허용합니다.
여러 문서 찾기 사용 예제에서 FindCursor
클래스의 유형을 지정하는 방법을 보여주는 코드 스니펫을 찾을 수 있습니다.
유형(Type) 안전 및 점 표기법
버전 5.0부터 기본적으로 Node.js 드라이버는 점 표기법으로 표현된 필드를 검색하는 작업에 대해 유형 안전을 제공하지 않습니다. 점 표기법은 중첩된 JSON 객체를 탐색하는 데 사용할 수 있는 구문입니다. 쿼리에 전달할 필터를 구성할 때 점 표기법으로 표현된 필드에 잘못 입력된 값을 지정하더라도 드라이버는 유형 오류를 발생시키지 않습니다.
다음 코드 스니펫은 ClassificationPet
인터페이스를 정의하며, 여기에는 개와 고양이의 속과 색을 지정할 수 있는 classification
필드가 포함되어 있습니다:
interface ClassificationPet { name: string; age: number; classification: { genus: "Canis" | "Felis"; color: string }; }
classification.color
값이 문자열이 아니라 부울인 경우에도 드라이버는 다음 코드 샘플에 대해 유형 오류를 발생시키지 않습니다.
await myColl.findOneAndDelete({ "classification.color": false });
StrictFilter
또는 StrictUpdateFilter
유형으로 필터를 구성하여 유형 검사를 활성화할 수 있습니다.
경고
StrictFilter
및 StrictUpdateFilter
유형은 실험용이므로 유형 오류가 없어야 하는 유효한 쿼리에 대해 유형 오류를 표시할 수 있습니다.
다음 코드 샘플에서는 필터에 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
어설션(assertion)을 사용해야 합니다. 이 메커니즘을 사용하면 입력 유형이 올바른 경우 코드가 성공적으로 컴파일될 수 있습니다.
다음 코드 스니펫은 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 드라이버 내 점 표기법의 제한 사항에 대해 자세히 알아보려면 재귀 유형 및 점 표기법 섹션을 참조하세요.
_id 필드 작업
MongoDB는 _id
을(를) 모델의 일부로 지정하는 것을 권장하지 않습니다. _id
필드를 생략하면 모델이 더 일반적이고 재사용 가능하며 애플리케이션에 중요한 데이터를 더 정확하게 모델링할 수 있습니다. 노드 드라이버의 타입스크립트(Typescript) 통합은 관련 메서드의 반환 유형에 _id
필드를 추가하는 작업을 처리합니다.
다음 섹션에서는 _id
필드를 사용하는 쓰기 및 읽기 작업에 대한 정보를 제공합니다.
삽입 작업 및 _id field
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>"); myColl.insertOne({ name: "Spot", age: 2 });
_id
필드에 대해 자세히 알아보려면 MongoDB 매뉴얼의 _id 필드를 참조하세요.
이 섹션에서 설명하는 유형, 인터페이스 및 클래스에 대해 자세히 알아보려면 다음 리소스를 참조하세요.
OptionalId API 문서
PkFactory API 문서
ObjectId 소스 코드
찾기 메서드 및 _id 필드
Collection
클래스의 find
및 findOne
메서드는 반환 유형에 _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 myColl.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 myColl.findOne({ name: "Spot", }); const id : number = document._id;
중요
프로젝션
찾기 메서드에서 프로젝션을 지정하는 경우 프로젝션된 문서의 구조를 반영하는 유형 매개변수를 찾기 메서드에 전달해야 합니다. 유형 매개변수가 없으면 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);
프로젝션을 적용하는 찾기 메서드가 포함된 실행 가능한 TypeScript 예시를 보려면 문서 찾기 페이지를 참조하세요.
이 섹션에서 설명하는 클래스 및 메서드에 대해 자세히 알아보려면 다음 API 문서를 참조하세요.
알려진 제한 사항
Node.js 드라이버의 다음 TypeScript 관련 제한 사항에 대해 알아보세요:
재귀 유형(Type) 및 점 표기법
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 매뉴얼의 점 표기법을 참조하세요.
상호 재귀
상호 재귀 유형은 두 유형에 다른 유형의 속성이 포함되어 있을 때 존재합니다. 펫이 핸들러를 가질 수 있도록 허용하고 핸들러가 펫을 가질 수 있도록 정의하여 펫 인터페이스를 상호 재귀적으로 업데이트할 수 있습니다. 다음 예시에서는 상호 재귀적인 Pet
및 Handler
인터페이스를 참조합니다.
interface Pet { handler?: Handler; name: string; age: number; } interface Handler { pet: Pet; name: string; }
Node.js 드라이버는 점 표기법을 통해 최대 8 깊이까지 레퍼런스된 상호 재귀 유형에 대해 유형 안전성을 제공합니다. 다음 코드 스니펫은 string
을 number
에 할당하고 레퍼런스 속성이 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"});