Menu Docs
Página inicial do Docs
/ / /
Controlador Node.js
/

TypeScript

Nesta página

  • Visão geral
  • Características
  • Parâmetros de tipo que estendem o documento
  • Digite parâmetros de qualquer tipo
  • Digite Segurança e Notação de Ponto
  • Trabalhando com o campo _id
  • Inserir Operações e o Campo _id
  • Encontrar métodos e o campo _id
  • Limitações conhecidas
  • Tipos recursivos e notação de ponto
  • Recursão mútua

Neste guia, você pode aprender sobre os recursos e limitações do TypeScript do driver MongoDB Node.js. TypeScript é uma linguagem de programação fortemente digitada que compila ao JavaScript.

O compilador TypeScript oferece verificação de tipo em tempo real. Editores de código que suporte TypeScript pode fornecer sugestões de preenchimento automático, exibir documentação embutida e identificar erros relacionados ao tipo.

Todas as funcionalidades do TypeScript do condutor são opcionais. Todo código JavaScript válido escrito com o driver também é um código TypeScript válido.

Para obter mais informações, consulte o site da Web do TypeScript.

Se você usar o TypeScript, poderá especificar um tipo para algumas classes no driver. Todas as classes que aceitam um parâmetro de tipo no driver têm o tipo padrão Document. A interface Document tem a seguinte definição:

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

Todos os tipos de objetos estendem a interface Document.

Para obter mais informações sobre tipos de objetos, consulte o manual do TypeScript.

As seguintes classes aceitam todos os tipos que estendem a interface Document:

Você pode passar um parâmetro de tipo que estenda a interface Document como esta:

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

Importante

Chaves que não estão no parâmetro Tipo recebem qualquer tipo

As chaves não listadas no parâmetro de tipo especificado recebem o tipo any. O seguinte trecho de código demonstra este comportamento:

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!" });

As seguintes classes aceitam todos os parâmetros do tipo:

Você pode encontrar um trecho de código que mostra como especificar um tipo para a classe FindCursor no Exemplo de uso do Find Multiple Documents.

A partir da versão 5.0, por padrão, o driver Node.js não oferece segurança de tipo para operações que procuram em campos expressos em notação de ponto. A anotação de ponto é uma sintaxe que você pode utilizar para navegar por objetos JSON aninhados. Quando você constrói um filtro para passar para uma query, o driver não emitirá um erro de tipo, mesmo que você especifique um valor digitado incorretamente para um campo expresso em notação de ponto.

O seguinte trecho de código define a interface ClassificationPet, que inclui um campo classification que permite especificar o gênero e a cor dos cães e gatos:

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

O driver não gera um erro de tipo para o seguinte exemplo de código, mesmo que o valor de classification.color seja um booleano em vez de uma string:

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

Você pode habilitar a verificação de tipo construindo filtros como tipos StrictFilter ou StrictUpdateFilter.

Aviso

Os tipos StrictFilter e StrictUpdateFilter são experimentais e podem mostrar incorretamente erros de tipo em queries válidas.

No exemplo de código a seguir, o filtro é atribuído a um tipo StrictFilter. Dado esse tipo de filtro, o driver do Node.js informa um erro de tipo porque o valor de classification.color é um booleano em vez de uma string.

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

O exemplo a seguir atribui um tipo StrictUpdateFilter a um filtro de atualização. O driver Node.js relata um erro de tipo porque o valor de classification.color é booleano em vez de uma string.

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

Para fazer query em uma coleção ou executar outra operação com uma chave que incorpore variáveis, você deve utilizar uma afirmação do as const ao especificar a chave. Esse mecanismo permite que seu código seja compilado com sucesso se os tipos de entrada estiverem corretos.

O seguinte trecho de código define a interface ClassificationPet e a interface Mealtime. ClassificationPet inclui um campo mealtimes que contém uma array de Mealtime interfaces, cada uma delas inclui um campo time:

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

O seguinte trecho de código executa uma operação de multa e atualização em uma coleção de documentos ClassificationPet. A operação atualiza o campo time aninhado da instância Mealtime no índice 1. A posição do índice é especificada pela variável mealCounter:

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

Para saber mais sobre notação de pontos, consulte Notação de pontos no manual do MongoDB.

Para saber mais sobre as limitações da notação de ponto no driver Node.js, consulte a seção Tipos Recursivos e Notação de Ponto .

O MongoDB não recomenda especificar o _id como parte do seu modelo. A omissão do campo _id torna o modelo mais genérico, reutilizável e com mais precisão modela os dados importantes para um aplicativo. Integração TypeScript driver Node trata de adicionar o campo _id aos tipos de retorno para métodos relevantes.

As seções a seguir fornecem informações sobre operações de escrita e leitura que utilizam o campo _id.

Como você especifica o campo _id nos parâmetros de tipo passados para a instância Collection afeta o comportamento das operações de inserção. A tabela a seguir descreve como especificações diferentes do campo _id afetam as operações de inserção:

_id tipo de campo
Tipo de exemplo
Necessário na inserção
Comportamento ao inserir
Não especificado
Não aplicável
Não
O driver cria um valor ObjectId para cada documento inserido.
Especificadas
{ _id: number };
Sim
Se você não especificar um valor para o campo _id em uma operação de inserção, o driver chamará um erro.
Especificado como opcional
{ _id?: number };
Não
Se você não especificar o campo _id em uma operação de inserção, o driver adicionará um valor de campo _id gerado pela fábrica da chave primária.

Se você precisar especificar o campo _id como obrigatório no tipo definido para representar documentos na coleção, mas não quiser especificar valores para o campo _id nas operações de inserção, use o tipo auxiliar OptionalId ao criar a coleção. O tipo OptionalId aceita um parâmetro de tipo como um argumento e retorna este tipo com um campo opcional _id.

O seguinte trecho de código define a interface IdPet, que inclui um tipo para o campo _id:

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

O código a seguir usa a interface anterior e o tipo OptionalId para inserir um documento sem especificar um valor para o campo _id:

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

Para saber mais sobre o campo _id , consulte O campo _id no manual MongoDB.

Para saber mais sobre os tipos, interfaces e classes discutidos nesta seção, consulte os seguintes recursos:

Os métodos find e findOne da classe Collection incluem o campo _id em seu tipo de retorno. O driver infere o tipo do campo _id retornado com base no parâmetro type que você passou para sua instância Collection.

Se o parâmetro de tipo que você passou para sua instância do Collection incluir o campo _id em seu esquema, o driver infere que o campo _id retornou do método é do tipo especificado no esquema.

No entanto, se o parâmetro de tipo que você passou para sua instância Collection não incluir o campo _id em seu esquema, o driver infere que o tipo do campo _id retornado do método é ObjectId.

Dica

O parâmetro de tipo passado para sua Collection influencia somente o tipo inferência dos campos retornados pelo método. O driver não converte o campo para o tipo especificado. O tipo de cada campo no seu tipo de parâmetro deve corresponder ao tipo do campo correspondente na coleção.

O código a seguir usa a interface Pet para retornar um documento com um _id inferido como sendo do tipo 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;

O código a seguir usa a interface IdNumberPet para retornar um documento com um _id inferido como sendo do tipo 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;

Importante

Projeção

Se você especificar uma projeção em um método find, deverá passar um parâmetro de tipo para o método find que reflita a estrutura dos documentos projetados. Sem um parâmetro de tipo, o TypeScript não pode verificar no momento da compilação se você está usando seus documentos projetados com segurança.

Para mostrar esse comportamento, o seguinte trecho de código passa por uma verificação de tipo, mas gera um erro no tempo de execução:

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

Para detectar esse erro no momento da compilação, passe um parâmetro de tipo que não inclua o campo _id para seu método de pesquisa:

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);

Para visualizar um exemplo executável do TypeScript que inclui um método find que aplica uma projeção, consulte a página Localizar um Documento.

Para saber mais sobre as classes e os métodos discutidos nesta seção, consulte a seguinte documentação da API:

Saiba mais sobre as seguintes limitações específicas do TypeScript do driver Node.js:

O driver Node.js não pode fornecer segurança de tipo em instâncias aninhadas de tipos recursivos referenciados por meio de notação de ponto.

Um tipo recursivo é um tipo que referencia a si mesmo. É possível atualizar a interface Pet para ser recursiva, permitindo que um Pet tenha seu próprio Pet. A seguir está a interface Pet recursiva:

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

Observação

Limite de profundidade

O driver do Node.js não atravessa tipos recursivos aninhados ao verificar chaves de notação de ponto para evitar atingir o limite de profundidade recursiva do TypeScript.

O seguinte trecho de código faz referência a uma instância aninhada da interface RecursivePet com um tipo incorreto usando notação de ponto, mas o compilador TypeScript não gera um erro de tipo:

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

O trecho de código a seguir faz referência a uma instância de nível superior da interface do RecursivePet com um tipo incorreto e gera um erro de tipo:

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

O erro criado pelo trecho de código anterior é o seguinte:

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>'.

Se você precisar ter segurança de tipo em instâncias aninhadas de tipos recursivos, você deve escrever sua query ou atualização sem notação de ponto.

Para saber mais sobre notação de pontos, consulte Notação de pontos no manual do MongoDB.

Um tipo mutuamente recursivo existe quando dois tipos contêm uma propriedade que é do tipo do outro. Você pode atualizar a interface Pet para que seja mutuamente recursiva, permitindo que um animal de estimação tenha um manipulador e definindo um manipulador para ter um animal de estimação. Os exemplos a seguir referenciam as interfaces Pet e Handler mutuamente recursivas:

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

O driver Node.js fornece segurança de tipo para tipos mutuamente recursivos referenciados por meio de notação de pontos até uma profundidade de oito. O seguinte trecho de código atribui um string a um number e gera um erro de tipo porque a propriedade referenciada está em uma profundidade de quatro:

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

O erro criado pelo trecho de código anterior é o seguinte:

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'.

Em uma profundidade maior ou igual a oito, o TypeScript compila seu código, mas nenhum tipo mais longo o verifica. O código a seguir atribui um string a uma propriedade number , mas não causa um erro de compilação porque a propriedade referenciada está em uma profundidade de 10:

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