Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions source/fundamentals/typescript.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ For more information on object types, see the
Type Parameters that Extend Document
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following classes accept all types that both extend
the ``Document`` interface and are not mutually recursive:
The following classes accept all types that extend the ``Document`` interface:

.. _node-mongodb-type-parameters-extend-document:

Expand All @@ -71,14 +70,13 @@ You can pass a type parameter that extends the ``Document`` interface like this:
:start-after: start-no-key
:end-before: end-no-key

To view an example of a mutually recursive type, which is not supported by the
:ref:`preceding classes <node-mongodb-type-parameters-extend-document>`,
see the :ref:`<node-driver-limitations-mutual-recursion>` section.
To view an example of a mutually recursive type, see the
:ref:`<node-driver-limitations-mutual-recursion>` section.

Type Parameters of Any Type
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following classes accept all type parameters that are not mutually recursive:
The following classes accept all type parameters:

.. _node-mongodb-type-parameters-any-type:

Expand All @@ -89,9 +87,8 @@ You can find a code snippet that shows how to specify a type for the ``FindCurso
class in the
:ref:`Find Multiple Documents Usage Example <node-driver-find-usage-example-code-snippet>`.

To view an example of a mutually recursive type, which is not supported by the
:ref:`preceding classes <node-mongodb-type-parameters-any-type>`,
see the :ref:`<node-driver-limitations-mutual-recursion>` section.
To view an example of a mutually recursive type, see the
:ref:`<node-driver-limitations-mutual-recursion>` section.
Comment thread
ajhuh-mdb marked this conversation as resolved.
Outdated


Type Safety and Dot Notation
Expand Down
63 changes: 38 additions & 25 deletions source/includes/limitations/limits.rst
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
Learn about the following TypeScript specific limitations of the {+driver-short+}:

- :ref:`No type safety for dot notation references to nested instances of recursive types <node-driver-recursive-types-dot-notation>`
- :ref:`No mutually recursive types <node-driver-limitations-mutual-recursion>`
- :ref:`Type safety depth limitations for mutually recursive types <node-driver-limitations-mutual-recursion>`
Comment thread
ajhuh-mdb marked this conversation as resolved.
Outdated

.. _node-driver-recursive-types-dot-notation:

Recursive Types and Dot Notation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. important:: Impacted Versions

- 4.3

@ajhuh-mdb ajhuh-mdb Dec 1, 2022

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this admonition since this affects nested recursive types from all versions after v4.3.1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: I thought v4.11 fixed this issue. What am I missing?

@ajhuh-mdb ajhuh-mdb Dec 2, 2022

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah so the "fix" I meant to refer to when we met was not type safety.

For clarification, the "issue" from 4.3.0 was that, previously, just the presence of a self-referential recursive schema type at all would cause a compilation error. The "fix" in 4.3.1 is that they allowed for the code to compile with a recursive schema type present, but their solution, in doing so, couldn't guarantee type checking (which becomes a separate "issue" from the one originally mentioned).

Sorry about that confusion 😅

- 4.4

The {+driver-short+} cannot provide type safety within nested instances of
**recursive types** referenced through dot notation.
Starting in version 4.3, the {+driver-short+} cannot provide type safety within
nested instances of **recursive types** referenced through dot notation.

A recursive type is a type that references itself. You can update
the :ref:`Pet <mongodb-node-typescript-pet-interface>` interface
Expand Down Expand Up @@ -80,40 +75,58 @@ in the MongoDB manual.
Mutual Recursion
~~~~~~~~~~~~~~~~

.. important:: Impacted Versions

- 4.3
- 4.4

You cannot specify a **mutually recursive** type as a type parameter.
In versions 4.3 through 4.10 of the {+driver-short+}, you cannot specify a
**mutually recursive** type as a type parameter. To specify a mutually
recursive type as a type parameter, use version 4.11 or newer.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: I think we can remove the version note if you're going to do a separate PR for versions 4.3-4.10. To me, it's implied that older versions of a driver might not be able to do things a new version would do.

Suggestion: Delete these lines, then make "mutually recursive" bold on line 82.

@ajhuh-mdb ajhuh-mdb Dec 2, 2022

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I do agree, I'm starting to skew towards keeping it. Just thinking of the case where a user using an older version (e.g. v4.3) goes to our docs site (which defaults to the current version v4.12) and sees the incorrect information without realizing they're on the incorrect version of the docs. Not sure if this is too much of an edge case, though... I'll likely bring it up as a q in #textual-dbx to get others' thoughts.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I'm good with whatever the team decides.


A mutually recursive type exists when two types contain a property that is of
the other's type. You can update the
:ref:`Pet <mongodb-node-typescript-pet-interface>` interface
to be mutually recursive by allowing a pet to have a handler, and defining a
handler to have a pet. The following are the mutually
the other's type. You can update the :ref:`Pet <mongodb-node-typescript-pet-interface>`
interface to be mutually recursive by allowing a pet to have a handler, and
defining a handler to have a pet. The following examples reference the mutually
recursive ``Pet`` and ``Handler`` interfaces:

.. code-block:: typescript
:emphasize-lines: 2, 8

interface MutuallyRecursivePet {
interface Pet {
Comment thread
ajhuh-mdb marked this conversation as resolved.
handler?: Handler;
name: string;
age: number;
}

interface Handler {
pet: MutuallyRecursivePet;
pet: Pet;
name: string;
}

The {+driver-short+} provides type safety for mutually recursive types
referenced through dot notation up to a depth of eight. The following code

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v4.11 release notes say nine, but tests of original PR say eight

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely worth confirming with the devs

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests are correct, I'll be updating the notes

snippet assigns a ``string`` to a ``number`` and raises a type error because
the referenced property is at a depth of four:

If you specify a mutually recursive type, the TypeScript compiler raises the
following error:
.. code-block:: typescript
:emphasize-lines: 3

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

The error raised by the preceding code snippet is as follows:

.. code-block:: none

error TS2615: Type of property 'r' circularly references itself in mapped type '{ [Key in keyof MutuallyRecursive]...
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. 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:

If you must apply a mutually recursive type to your classes, use version 4.2 of
the {+driver-short+}.
.. code-block:: typescript
:emphasize-lines: 3

database
.collection<Pet>("<your collection>")
.findOne({'handler.pet.handler.pet.handler.pet.handler.pet.handler.pet.age': "four"});
40 changes: 22 additions & 18 deletions source/whats-new.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,46 +64,50 @@ To learn more, see the `v4.12.0 Release Highlights <https://github.com/mongodb/n
What's New in 4.11
------------------

The 4.11 {+driver-short+} release includes **recursive schema support**,
meaning that you can use recursive types as the schema in the
``Collection`` class. The driver also provides type safety for dot
notation queries up to a depth of nine in this release. Typescript compiles
your code beyond a depth of nine, but types fall back to ``any`` at
this level. The recursive type depth limit is a current limitation in
TypeScript.
The 4.11 {+driver-short+} release includes added support for **mutually
recursive** collection schema types. The driver also provides type safety for
dot notation queries up to a depth of eight in this release. Typescript compiles

@ajhuh-mdb ajhuh-mdb Dec 1, 2022

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v4.11 release notes say nine, but tests of original PR say eight

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above--confirm this with devs

your code beyond a depth of eight, but types fall back to ``any`` at this level.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: Somewhat confusing

Suggestion:

Suggested change
dot notation queries up to a depth of eight in this release. Typescript compiles
your code beyond a depth of eight, but types fall back to ``any`` at this level.
dot notation queries up to a depth of eight in this release. At a depth greater than or equal to eight, all dot-notation properties on recursive types are assigned the ``any`` type.

(Is "properties" the right word here?)

@ajhuh-mdb ajhuh-mdb Dec 2, 2022

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the important thing for users to know here is that their code won't deal with a compilation error, rather than knowing the specifics of what type they'll fall back to.

The bit about the any type assignment is more so for users to know why they won't run into a compilation error. Will try to restructure the sentence to mitigate confusion

The recursive type depth limit is a current limitation in TypeScript.
Comment thread
ajhuh-mdb marked this conversation as resolved.
Outdated

Recursive Schema Type Checking Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mutually Recursive Schema Type Checking Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Suppose we have a collection of type ``Collection<CircularSchema>``:
Suppose we have a collection of type ``Collection<Author>`` which contains the
Comment thread
ajhuh-mdb marked this conversation as resolved.
Outdated
following mutually recursive types:

.. code-block:: js
:copyable: false

interface CircularSchema {
interface Author {
name: string;
ref: CircularSchema;
bestBook: Book;
}

TypeScript enforces type checking below a depth of nine. The following
interface Book {
title: string;
author: Author;
}

TypeScript enforces type checking below a depth of eight. The following
Comment thread
ajhuh-mdb marked this conversation as resolved.
Outdated
code causes a TypeScript compilation error because the ``name`` property
value must be a ``string`` type:

.. code-block:: js
:copyable: false

collection.findOne({ 'ref.ref.ref.name': 25 })
collection.findOne({ 'bestBook.author.bestBook.title': 25 })

At a depth greater than nine, TypeScript compiles your code but no
longer type checks it. The following code assigns an ``int`` to a ``string``
At a depth greater than or equal to eight, TypeScript compiles your code but no
longer type checks it. The following code assigns a ``number`` to a ``string``
Comment thread
ajhuh-mdb marked this conversation as resolved.
Outdated
property but does not cause a compilation error because the
referenced property is at a depth of 11:
referenced property is at a depth of 10:

.. code-block:: js
:copyable: false

collection.findOne({
'ref.ref.ref.ref.ref.ref.ref.ref.ref.ref.name': 25
''bestBook.author.bestBook.author.bestBook.author.bestBook.author.bestBook.author.name': 25
Comment thread
mongoKart marked this conversation as resolved.
Outdated
})

To learn more, see the `v4.11.0 Release Highlights <https://github.com/mongodb/node-mongodb-native/releases/tag/v4.11.0>`__.
Expand Down