-
Notifications
You must be signed in to change notification settings - Fork 52
DOCSP-25723 Updates to Mutually Recursive Schema Types #459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
91e0f0f
c003c63
041baff
f65113a
da3bbe3
3707291
45b2fb1
b454952
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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>` | ||
|
ajhuh-mdb marked this conversation as resolved.
Outdated
|
||
|
|
||
| .. _node-driver-recursive-types-dot-notation: | ||
|
|
||
| Recursive Types and Dot Notation | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| .. important:: Impacted Versions | ||
|
|
||
| - 4.3 | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question: I thought v4.11 fixed this issue. What am I missing?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
|
@@ -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. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 { | ||
|
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 | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely worth confirming with the devs
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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"}); | ||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -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 | ||||||||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Issue: Somewhat confusing Suggestion:
Suggested change
(Is "properties" the right word here?)
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||||||||
| The recursive type depth limit is a current limitation in TypeScript. | ||||||||
|
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 | ||||||||
|
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 | ||||||||
|
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`` | ||||||||
|
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 | ||||||||
|
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>`__. | ||||||||
|
|
||||||||
Uh oh!
There was an error while loading. Please reload this page.