Skip to content

Commit 054f1ba

Browse files
(DOCSP-20071) Update TS Limitations (#275)
1 parent ca4e25a commit 054f1ba

File tree

6 files changed

+174
-99
lines changed

6 files changed

+174
-99
lines changed

source/code-snippets/typescript/dot-notation.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ const collection = database.collection<TestType>("<your collection>");
1515
await collection.updateOne({}, { $set: { field: { nested: "A string" } } });
1616
// end-error
1717
// start-no-key
18-
interface TestNumber {
19-
myNumber: number;
18+
interface User {
19+
email: string;
2020
}
2121

22-
const database = client.db("<your db>");
23-
const collection = db.collection<TestNumber>("...");
24-
collection.find({ someRandomKey: "Accepts any type!" });
22+
const database = client.db("<your database>");
23+
const collection = db.collection<User>("<your collection>");
24+
collection.find({ age: "Accepts any type!" });
2525
// end-no-key

source/code-snippets/typescript/extend-document.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
interface Pet {
22
name: string;
33
age: number;
4-
cute: true;
54
}
65

76
const database = client.db("<your database>");

source/code-snippets/typescript/note-on-dot-notation.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

source/fundamentals/typescript.txt

Lines changed: 58 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,26 @@ All classes that accept a type parameter in the driver have the default type
3636
[key: string]: any;
3737
}
3838

39-
Any object type can extend the ``Document`` interface.
39+
All object types extend the ``Document`` interface.
4040

4141
For more information on object types, see the
4242
`TypeScript handbook <https://www.typescriptlang.org/docs/handbook/2/objects.html>`__.
4343

44-
Extend Document
45-
~~~~~~~~~~~~~~~
44+
Type Parameters that Extend Document
45+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4646

47-
The following classes accept any type that extends the ``Document``
48-
interface:
47+
The following classes accept all types that both extend
48+
the ``Document`` interface and are not mutually recursive:
49+
50+
.. _node-mongodb-type-parameters-extend-document:
4951

5052
- `Collection <{+api+}/classes/Collection.html>`__
5153
- `ChangeStream <{+api+}/classes/ChangeStream.html>`__
5254

5355
You can pass a type parameter that extends the ``Document`` interface like this:
5456

57+
.. _mongodb-node-typescript-pet-interface:
58+
5559
.. literalinclude:: /code-snippets/typescript/extend-document.ts
5660
:language: typescript
5761
:linenos:
@@ -67,10 +71,16 @@ You can pass a type parameter that extends the ``Document`` interface like this:
6771
:start-after: start-no-key
6872
:end-before: end-no-key
6973

70-
Any Type
71-
~~~~~~~~
74+
To view an example of a mutually recursive type, which is not supported by the
75+
:ref:`preceding classes <node-mongodb-type-parameters-extend-document>`,
76+
see the :ref:`<node-driver-limitations-mutual-recursion>` section.
77+
78+
Type Parameters of Any Type
79+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
7280

73-
The following classes accept any type parameter:
81+
The following classes accept all type parameters that are not mutually recursive:
82+
83+
.. _node-mongodb-type-parameters-any-type:
7484

7585
- `FindCursor <{+api+}/classes/FindCursor.html>`__
7686
- `AggregationCursor <{+api+}/classes/AggregationCursor.html>`__
@@ -79,81 +89,60 @@ You can find a code snippet that shows how to specify a type for the ``FindCurso
7989
class in the
8090
:ref:`Find Multiple Documents Usage Example <node-driver-find-usage-example-code-snippet>`.
8191

82-
Limitations
83-
-----------
84-
85-
.. _node-driver-typescript-limitations-dot-notation:
86-
87-
The driver cannot infer the type of values with keys containing **dot
88-
notation**. Dot notation is a property access syntax for navigating BSON objects.
89-
Click on the tabs to see code snippets that highlight this behavior:
90-
91-
.. tabs::
92-
93-
.. tab:: Dot Notation
94-
:tabid: dot-notation
95-
96-
The following code snippet does not raise a type error:
92+
To view an example of a mutually recursive type, which is not supported by the
93+
:ref:`preceding classes <node-mongodb-type-parameters-any-type>`,
94+
see the :ref:`<node-driver-limitations-mutual-recursion>` section.
9795

98-
.. literalinclude:: /code-snippets/typescript/dot-notation.ts
99-
:language: typescript
100-
:linenos:
101-
:start-after: start-no-error
102-
:end-before: end-no-error
10396

104-
.. tab:: Nested Objects
105-
:tabid: nested-objects
97+
Type Safety and Dot Notation
98+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10699

107-
The following code snippet raises a type error:
100+
If you specify a query or update with **dot notation**, the {+driver-short+}
101+
provides type safety if your query or update does not
102+
:ref:`reference a nested instance of a recursive type <node-driver-recursive-types-dot-notation>`.
103+
Dot notation is a syntax you can use to navigate nested JSON objects.
108104

109-
.. literalinclude:: /code-snippets/typescript/dot-notation.ts
110-
:language: typescript
111-
:linenos:
112-
:start-after: start-error
113-
:end-before: end-error
105+
The following code snippet defines the ``ClassificationPet`` interface,
106+
which includes a ``classification`` field that enables you to specify the
107+
genus and color of dogs and cats:
114108

115-
This is the error:
109+
.. code-block:: typescript
116110

117-
.. code-block:: text
111+
interface ClassificationPet {
112+
name: string;
113+
age: number;
114+
classification: { genus: "Canis" | "Felis"; color: string };
115+
}
118116

119-
Type 'string' is not assignable to type 'number'.
117+
The following code snippet correctly raises a type error when specifying
118+
the genus of an unsupported animal in a query:
120119

121-
Despite the lack of type safety, we still recommend that you use dot notation to
122-
access nested fields in query and update documents when you use TypeScript. You
123-
must manually check that your nested field values have your intended type.
120+
.. code-block:: typescript
124121

125-
.. note:: Reason To Use Dot Notation
122+
database
123+
.collection<ClassificationPet>("<your collection>")
124+
.find({ "classification.genus": "Sylvilagus" });
126125

127-
In the MongoDB Query Language, you must match a subdocument exactly
128-
when specifying subdocuments in a query. Dot notation allows you to query
129-
nested fields without matching subdocuments exactly.
126+
The type error raised by the preceding code snippet is as follows:
130127

131-
To show this behavior, lets say you have a collection containing
132-
only the following document:
128+
.. code-block:: none
133129

134-
.. code-block:: json
130+
No overload matches this call.
131+
...
132+
Type '"Sylvilagus"' is not assignable to type 'Condition<"Canis" | "Felis">'.
135133

136-
{ field: { s1: "hi", s2: "bye" } }
134+
To learn more about dot notation, see
135+
:manual:`Dot Notation </core/document/#dot-notation>`
136+
in the MongoDB manual.
137137

138-
The following query returns no results from this collection, as the value of
139-
``field`` does not exactly match ``{ s1: "hi" }``:
138+
To learn more about the limitations of dot notation in the
139+
{+driver-short+}, see the
140+
:ref:`<node-driver-recursive-types-dot-notation>`
141+
section.
140142

141-
.. literalinclude:: /code-snippets/typescript/note-on-dot-notation.ts
142-
:language: typescript
143-
:linenos:
144-
:start-after: start-no-doc
145-
:end-before: end-no-doc
146-
147-
The following queries both return your document:
148-
149-
.. literalinclude:: /code-snippets/typescript/note-on-dot-notation.ts
150-
:language: typescript
151-
:linenos:
152-
:start-after: start-doc
153-
:end-before: end-doc
143+
.. _node-driver-limitations:
154144

155-
The syntax of the query that does not use dot notation is cumbersome and hard
156-
to understand, and may not be worth the type safety obtained from
157-
avoiding dot notation.
145+
Limitations of Driver Version {+version+}
146+
---------------------------------
158147

159-
For more information on dot notation, see :manual:`the MongoDB Manual </core/document/#dot-notation>`.
148+
.. include:: includes/limitations/{+version+}.rst

source/includes/limitations/4.3.rst

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
Learn about the following TypeScript specific limitations of
2+
version 4.3 of the {+driver-short+}:
3+
4+
- :ref:`No type safety for dot notation references to nested instances of recursive types <node-driver-recursive-types-dot-notation>`
5+
- :ref:`No mutually recursive types <node-driver-limitations-mutual-recursion>`
6+
7+
.. _node-driver-recursive-types-dot-notation:
8+
9+
Recursive Types and Dot Notation
10+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11+
12+
The {+driver-short+} cannot provide type safety within nested instances of
13+
**recursive types** referenced through dot notation.
14+
15+
A recursive type is a type that references itself. You can update
16+
the :ref:`Pet <mongodb-node-typescript-pet-interface>` interface
17+
to be recursive by allowing a pet to have its own pet. The following is the
18+
recursive ``Pet`` interface:
19+
20+
.. _node-driver-limitations-recursive-pet:
21+
22+
.. code-block:: typescript
23+
:emphasize-lines: 2
24+
25+
interface RecursivePet {
26+
pet?: RecursivePet;
27+
name: string;
28+
age: number;
29+
}
30+
31+
.. note:: Depth Limit
32+
33+
The {+driver-short+} does not traverse nested recursive types when
34+
type checking dot notation keys to avoid hitting
35+
TypeScript's recursive depth limit.
36+
37+
The following code snippet references a nested instance of the
38+
:ref:`RecursivePet <node-driver-limitations-recursive-pet>` interface
39+
with an incorrect type using dot notation, but the TypeScript compiler
40+
does not raise a type error:
41+
42+
.. code-block:: typescript
43+
:emphasize-lines: 3
44+
45+
database
46+
.collection<RecursivePet>("<your collection>")
47+
.findOne({ "pet.age": "Spot" });
48+
49+
The following code snippet references a top-level instance of the
50+
``RecursivePet`` interface with an incorrect type and raises a type error:
51+
52+
.. code-block:: typescript
53+
:emphasize-lines: 3
54+
55+
database
56+
.collection<RecursivePet>("<your collection>")
57+
.findOne({ pet: "Spot" });
58+
59+
The error raised by the preceding code snippet is as follows:
60+
61+
.. code-block:: none
62+
63+
index.ts(19,59): error TS2769: No overload matches this call.
64+
The last overload gave the following error.
65+
Type 'string' is not assignable to type 'Condition<Pet>'.
66+
67+
If you must have type safety within nested instances of recursive types,
68+
you must write your query or update without dot notation.
69+
70+
To learn more about dot notation, see
71+
:manual:`Dot Notation </core/document/#dot-notation>`
72+
in the MongoDB manual.
73+
74+
.. _node-driver-limitations-mutual-recursion:
75+
76+
Mutual Recursion
77+
~~~~~~~~~~~~~~~~
78+
79+
You cannot specify a **mutually recursive** type as a type parameter in version
80+
4.3 of the driver.
81+
82+
A mutually recursive type exists when two types contain a property that is of
83+
the other's type. You can update the
84+
:ref:`Pet <mongodb-node-typescript-pet-interface>` interface
85+
to be mutually recursive by allowing a pet to have a handler, and defining a
86+
handler to have a pet. The following are the mutually
87+
recursive ``Pet`` and ``Handler`` interfaces:
88+
89+
.. code-block:: typescript
90+
:emphasize-lines: 2, 8
91+
92+
interface MutuallyRecursivePet {
93+
handler?: Handler;
94+
name: string;
95+
age: number;
96+
}
97+
98+
interface Handler {
99+
pet: MutuallyRecursivePet;
100+
name: string;
101+
}
102+
103+
If you specify a mutually recursive type, the TypeScript compiler raises the
104+
following error:
105+
106+
.. code-block:: none
107+
108+
error TS2615: Type of property 'r' circularly references itself in mapped type '{ [Key in keyof MutuallyRecursive]...
109+
110+
If you must apply a mutually recursive type to your classes, use version 4.2 of
111+
the {+driver-short+}.

source/usage-examples/bulkWrite.txt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,6 @@ to ``bulkWrite()`` includes examples of ``insertOne``, ``updateMany``, and
8787
:language: typescript
8888
:linenos:
8989

90-
.. important:: Dot Notation Loses Type Safety
91-
92-
You lose type-safety for values when you use dot notation in keys. For
93-
more information, see our guide on
94-
:ref:`TypeScript in the driver <node-driver-typescript-limitations-dot-notation>`.
95-
9690
When you run the preceding example, you should see the following output:
9791

9892
.. code-block:: javascript

0 commit comments

Comments
 (0)