From 91e0f0fcabc4a258216afeb3e9fe966cf0950c0f Mon Sep 17 00:00:00 2001 From: Alison Huh Date: Thu, 1 Dec 2022 13:54:21 -0500 Subject: [PATCH 1/8] DOCSP-25723 Updates to Mutually Recursive Schema Types --- source/fundamentals/typescript.txt | 15 +++---- source/includes/limitations/limits.rst | 59 ++++++++++++++++---------- source/whats-new.txt | 40 +++++++++-------- 3 files changed, 64 insertions(+), 50 deletions(-) diff --git a/source/fundamentals/typescript.txt b/source/fundamentals/typescript.txt index eb1848c6e..55a105612 100644 --- a/source/fundamentals/typescript.txt +++ b/source/fundamentals/typescript.txt @@ -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: @@ -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 `, -see the :ref:`` section. +To view an example of a mutually recursive type, see the +:ref:`` 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: @@ -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 `. -To view an example of a mutually recursive type, which is not supported by the -:ref:`preceding classes `, -see the :ref:`` section. +To view an example of a mutually recursive type, see the +:ref:`` section. Type Safety and Dot Notation diff --git a/source/includes/limitations/limits.rst b/source/includes/limitations/limits.rst index 26e43e29f..5a99a984e 100644 --- a/source/includes/limitations/limits.rst +++ b/source/includes/limitations/limits.rst @@ -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 ` -- :ref:`No mutually recursive types ` +- :ref:`Mutually recursive types ` .. _node-driver-recursive-types-dot-notation: Recursive Types and Dot Notation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. important:: Impacted Versions - - - 4.3 - - 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 ` interface @@ -80,18 +75,14 @@ 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. A mutually recursive type exists when two types contain a property that is of -the other's type. You can update the -:ref:`Pet ` 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 ` +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 @@ -107,13 +98,35 @@ recursive ``Pet`` and ``Handler`` interfaces: pet: MutuallyRecursivePet; 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 +snippet assigns a ``string`` to a ``number`` and raises a type error because +the referenced property is at a depth of four: + +.. code-block:: typescript + :emphasize-lines: 3 -If you specify a mutually recursive type, the TypeScript compiler raises the -following error: + database + .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 | undefined'. -If you must apply a mutually recursive type to your classes, use version 4.2 of -the {+driver-short+}. +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: + +.. code-block:: typescript + :emphasize-lines: 3 + + database + .collection("") + .findOne({'handler.pet.handler.pet.handler.pet.handler.pet.handler.pet.age': "four"}); diff --git a/source/whats-new.txt b/source/whats-new.txt index 585fd4794..57bc36d98 100644 --- a/source/whats-new.txt +++ b/source/whats-new.txt @@ -64,46 +64,50 @@ To learn more, see the `v4.12.0 Release Highlights ``: +Suppose we have a collection of type ``Collection`` which contains the +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 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`` 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 }) To learn more, see the `v4.11.0 Release Highlights `__. From c003c63ff2a21d87f18c18575627e3982957c140 Mon Sep 17 00:00:00 2001 From: Alison Huh Date: Thu, 1 Dec 2022 14:56:41 -0500 Subject: [PATCH 2/8] edit mutually recursive pet code block --- source/includes/limitations/limits.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/includes/limitations/limits.rst b/source/includes/limitations/limits.rst index 5a99a984e..c475e67b2 100644 --- a/source/includes/limitations/limits.rst +++ b/source/includes/limitations/limits.rst @@ -88,14 +88,14 @@ recursive ``Pet`` and ``Handler`` interfaces: .. code-block:: typescript :emphasize-lines: 2, 8 - interface MutuallyRecursivePet { - handler?: Handler; + interface Pet { + handler: Handler; name: string; age: number; } interface Handler { - pet: MutuallyRecursivePet; + pet: Pet; name: string; } From 041baffbe553b54fec1233d72945e0aa18740f96 Mon Sep 17 00:00:00 2001 From: Alison Huh Date: Thu, 1 Dec 2022 14:58:30 -0500 Subject: [PATCH 3/8] edit collection schema name --- source/includes/limitations/limits.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/includes/limitations/limits.rst b/source/includes/limitations/limits.rst index c475e67b2..a344f9c5a 100644 --- a/source/includes/limitations/limits.rst +++ b/source/includes/limitations/limits.rst @@ -89,7 +89,7 @@ recursive ``Pet`` and ``Handler`` interfaces: :emphasize-lines: 2, 8 interface Pet { - handler: Handler; + handler?: Handler; name: string; age: number; } @@ -108,7 +108,7 @@ the referenced property is at a depth of four: :emphasize-lines: 3 database - .collection("") + .collection("") .findOne({'handler.pet.handler.pet.age': "four"}); The error raised by the preceding code snippet is as follows: @@ -128,5 +128,5 @@ is at a depth of 10: :emphasize-lines: 3 database - .collection("") + .collection("") .findOne({'handler.pet.handler.pet.handler.pet.handler.pet.handler.pet.age': "four"}); From f65113aa05604628fbbc4fcffb81f2af36bcf339 Mon Sep 17 00:00:00 2001 From: Alison Huh Date: Thu, 1 Dec 2022 15:14:52 -0500 Subject: [PATCH 4/8] more specific limitations menu text --- source/includes/limitations/limits.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/includes/limitations/limits.rst b/source/includes/limitations/limits.rst index a344f9c5a..203aba1ba 100644 --- a/source/includes/limitations/limits.rst +++ b/source/includes/limitations/limits.rst @@ -1,7 +1,7 @@ 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 ` -- :ref:`Mutually recursive types ` +- :ref:`Type safety depth limitations for mutually recursive types ` .. _node-driver-recursive-types-dot-notation: From da3bbe3d5a45fd73fa23166d5c11d422723a6adc Mon Sep 17 00:00:00 2001 From: Alison Huh Date: Fri, 2 Dec 2022 13:54:40 -0500 Subject: [PATCH 5/8] MW comment edits --- source/fundamentals/typescript.txt | 6 ------ source/includes/limitations/limits.rst | 2 +- source/whats-new.txt | 15 ++++++++------- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/source/fundamentals/typescript.txt b/source/fundamentals/typescript.txt index 55a105612..dce932b04 100644 --- a/source/fundamentals/typescript.txt +++ b/source/fundamentals/typescript.txt @@ -70,9 +70,6 @@ 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, see the -:ref:`` section. - Type Parameters of Any Type ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -87,9 +84,6 @@ 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 `. -To view an example of a mutually recursive type, see the -:ref:`` section. - Type Safety and Dot Notation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/source/includes/limitations/limits.rst b/source/includes/limitations/limits.rst index 203aba1ba..11ff7b2af 100644 --- a/source/includes/limitations/limits.rst +++ b/source/includes/limitations/limits.rst @@ -1,7 +1,7 @@ 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 ` -- :ref:`Type safety depth limitations for mutually recursive types ` +- :ref:`Depth limitations on type safety for mutually recursive types ` .. _node-driver-recursive-types-dot-notation: diff --git a/source/whats-new.txt b/source/whats-new.txt index 57bc36d98..af195f5c7 100644 --- a/source/whats-new.txt +++ b/source/whats-new.txt @@ -66,14 +66,15 @@ What's New in 4.11 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 -your code beyond a depth of eight, but types fall back to ``any`` at this level. -The recursive type depth limit is a current limitation in TypeScript. +dot notation queries up to a depth of eight in this release. At a depth greater +than or equal to eight, Typescript successfully compiles your code but does not +provide type safety because all type checking defaults to ``any`` at this +level. This depth limit is a current limitation in TypeScript. Mutually Recursive Schema Type Checking Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suppose we have a collection of type ``Collection`` which contains the +Suppose we have a collection of type ``Collection`` that contains the following mutually recursive types: .. code-block:: js @@ -89,7 +90,7 @@ following mutually recursive types: author: Author; } -TypeScript enforces type checking below a depth of eight. The following +TypeScript enforces type checking up to a depth of eight. The following code causes a TypeScript compilation error because the ``name`` property value must be a ``string`` type: @@ -99,8 +100,8 @@ value must be a ``string`` type: collection.findOne({ 'bestBook.author.bestBook.title': 25 }) 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`` -property but does not cause a compilation error because the +longer type checks it. For example, the following code assigns a ``number`` to a +``string`` property but does not cause a compilation error because the referenced property is at a depth of 10: .. code-block:: js From 37072911d91f77590cbef84efdc71c08c61f7f85 Mon Sep 17 00:00:00 2001 From: Alison Huh Date: Fri, 2 Dec 2022 16:26:36 -0500 Subject: [PATCH 6/8] rephrase confusing sentence --- source/whats-new.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/whats-new.txt b/source/whats-new.txt index af195f5c7..03109dac6 100644 --- a/source/whats-new.txt +++ b/source/whats-new.txt @@ -66,10 +66,10 @@ What's New in 4.11 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. At a depth greater +dot-notation queries up to a depth of eight in this release. At a depth greater than or equal to eight, Typescript successfully compiles your code but does not -provide type safety because all type checking defaults to ``any`` at this -level. This depth limit is a current limitation in TypeScript. +provide type safety. This depth limit on recursive types is a current limitation +of TypeScript. Mutually Recursive Schema Type Checking Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 45b2fb19320c0b3386b42239a9563c39abb3b8ad Mon Sep 17 00:00:00 2001 From: Alison Huh Date: Fri, 2 Dec 2022 17:13:57 -0500 Subject: [PATCH 7/8] remove warning notes for v4.3-4.10 behavior --- source/includes/limitations/limits.rst | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/source/includes/limitations/limits.rst b/source/includes/limitations/limits.rst index 11ff7b2af..1d298c31a 100644 --- a/source/includes/limitations/limits.rst +++ b/source/includes/limitations/limits.rst @@ -8,8 +8,8 @@ Learn about the following TypeScript specific limitations of the {+driver-short+ Recursive Types and Dot Notation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Starting in version 4.3, the {+driver-short+} cannot provide type safety within -nested instances of **recursive types** referenced through dot notation. +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 ` interface @@ -75,11 +75,7 @@ in the MongoDB manual. Mutual Recursion ~~~~~~~~~~~~~~~~ -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. - -A mutually recursive type exists when two types contain a property that is of +A **mutually recursive** type exists when two types contain a property that is of the other's type. You can update the :ref:`Pet ` 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 From b454952bead0f967bdd9603670fce30ba746b4ec Mon Sep 17 00:00:00 2001 From: Mike Woofter <108414937+mongoKart@users.noreply.github.com> Date: Mon, 5 Dec 2022 11:41:06 -0600 Subject: [PATCH 8/8] Apply suggestions from code review Co-authored-by: Neal Beeken --- source/whats-new.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/whats-new.txt b/source/whats-new.txt index 03109dac6..dfdca1658 100644 --- a/source/whats-new.txt +++ b/source/whats-new.txt @@ -108,7 +108,7 @@ referenced property is at a depth of 10: :copyable: false collection.findOne({ - ''bestBook.author.bestBook.author.bestBook.author.bestBook.author.bestBook.author.name': 25 + 'bestBook.author.bestBook.author.bestBook.author.bestBook.author.bestBook.author.name': 25 }) To learn more, see the `v4.11.0 Release Highlights `__.