-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
feat(NODE-3589): support dot-notation attributes in Filter #2972
Conversation
Unrelated to this PR: when I run |
Hi @avaly thanks for the contribution! This does look like something we would be interested in merging but there's some concern about what this does to compile times. Do you have any reference on how a deeply nested schema could impact compilation time? As for the TS failures, our package-lock file should have our TS version set to 4.3.5 (even thought package.json has |
I am happy to run some tests. How do you suggest I measure the impact? Simply track the time it takes to compile a big schema? How have you done similar measurements in the past? |
There appears to be some failures with the tsd tests.
I think we can establish a base level, a simple schema like the Pet one in the testing examples, does compilation time change before and after your changes? We can calculate out some worst case scenarios in terms of how many keys TS going to have to generate and typecheck but if we can already see a difference with simple examples that would give some indicator. The risk is not really compilation times for shipping JS but potentially slowing down VSCode's insights. I still have to take a close look at the Join helper, does this support array notation too? And this should support any level of nesting right? Can you add a test for more nested levels? just to sanity check. |
I fixed some of the TS issues. Unfortunately using these new helper types, schemas which reference themselves internally are not going to be supported (e.g. I still can't figure out how to solve the union schema TS error. TBH I wasn't even aware that was valid syntax. |
b840501
to
52b858e
Compare
I ran a compilation time test locally on this branch and on the latest commit on the I used this test file (interface used from 4.1 branch
this branch
The time diffs are minimal. But worth the safety they bring IMHO. |
Thanks for running the diagnostics! @dariakp and I figured out that calculating how many keys typescript has to build its the same formula as calculating the total number of vertices in a complete tree. Each node being an interface and the edges leaving it being the number of keys. So it means that the generation space doesn't grow as fast as I had assumed it would. It still does create a lot of keys but not exponential growth. Unfortunately, I believe the self referencing schema as well as the exclusive union issue is a blocker. The union tests come from the community types (and I think from the Typescript handbook, but its been a while). No longer supporting these would be a breaking change. I don't believe there is, but do you know if there is any way to detect these usage styles and omit the dot-notation support? Beyond the scope of what we're addressing here but it would make sense to investigate supporting array notation if we were to make this project fully support MongoDB syntax. |
I'll try to see if I can find a way to omit the self-referenced schemas. I believe array-support is easy to add also, I'll look into that as well. However, for the union schemas, I'm trying to figure out where those tests came from and if they actually make sense to keep around. They seems to have been added in #2767. But they're not in the latest tests from DefinitelyTyped version in DefinitelyTyped/DefinitelyTyped#54510. Do you have any clue of their source @nbbeeken (since you were the author of #2767)? |
52b858e
to
f0a3e4f
Compare
I've added support for dot-notation array fields. |
f0a3e4f
to
da0454a
Compare
@avaly Please note that there was a CI issue that blocked all tests from running which necessitated a change to our main branch for the fix, could you rebase your branch to pull them in here? |
da0454a
to
35f962b
Compare
@dariakp I rebased on the latest @nbbeeken What do you think about removing that union test case? (#2972 (comment)) |
I think we can drop it safely, I wasn't able to find where it originally came from, it might have been something that I considered should work and be supported, but it isn't native to TS as in it requires arguably significant manual type logic. I plan to do a full review of this very soon, but if you wanna go ahead and remove those now please feel free. |
35f962b
to
4c7c54a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed some tests for extra cases I found. I think we can make nested arrays work, thoughts?
@nbbeeken Thanks for the extra tests. I fixed the outstanding issues. |
I fixed some issues that showed up after the TypeScript v4.5 upgrade. |
d51fc16
to
64ee1bf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much for your patience as we consider this feature, I just made a small fix to our linting, and this otherwise LGTM. I'll let the rest of the team take a look themselves but 👍
Hey @avaly, thanks again for contributing this PR! I wanted to follow up and see if you've had a chance to look at Neal's comment or my comment. Neal's comment is definitely blocking this PR from being ready to merge but mine is not (it would just be nice to have 😄). We think that the PR looks great overall, and would like to try and merge it by the end of the week. Would you have a chance to take resolve the merge conflicts and address Neal's comment before then? If not, I'm happy to take over and get it ready to merge. Thank again for your help! |
@baileympearson I'll try to look into it this week, but I worry the union type issue might be hard to support. |
@avaly If we can't resolve the union typing issue, that's all right. But we will need to resolve the merge conflict and add |
9e47626
to
70685e0
Compare
@baileympearson @nbbeeken I've rebased this PR on the latest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made some small fixes to the nested types escape hatch:
RegExp
/Buffer
/Uint8Array
- these are directly serialized by the BSON lib((...args: any[]) => any)
- the Function type is recursive, and you can serialize them with theserializeFunctions
flag.{ _bsontype: string }
- this should cover all our custom BSON types so we don't have to worry about listing them each out.
I think this is ready! (just waiting on CI) LGTM! Thanks again @avaly this is a really awesome feature add!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you!
: unknown | ||
: unknown; | ||
|
||
// We dont't support nested circular references |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could add support for circular types using an accumulator as depth checker and bail out when too deep. This works around the TS error "TS2589: Type instantiation is excessively deep and possibly infinite.". A max depth of 10 is probably enough for most cases without making the TS checker too slow.
Example
type O<T, K extends string, Prefix extends string, Depth extends number[]> = K extends keyof T ? { [_ in `${Prefix}.${K}`]: T[K] } & (T[K] extends object ? SubObjects<T[K], Extract<keyof T[K], string>, `${Prefix}.${K}`, [...Depth, 1]> : {}) : {};
type SubObjects<T, K extends string, Prefix extends string, Depth extends number[]> =
Depth['length'] extends 10 ? {} : //bail out when too deep
K extends keyof T ? T[K] extends Array<infer A> ? SubObjects<A, Extract<keyof A, string>, `${Prefix}.${K}.${number}`, [...Depth, 1]> :
T[K] extends object ? O<T[K], Extract<keyof T[K], string>, Prefix extends '' ? K : `${Prefix}.${K}`, Depth> : { [P in Prefix extends '' ? K :`${Prefix}.${K}`]: T[K] } : {};
type FilterQuery<T> = SubObjects<T, Extract<keyof T, string>, '', []>;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Description
Currently, dot-notation attributes (e.g.
foo.bar
) in filter objects do not get any type checks.What changed?
This PR changes the implementation of the
Filter
type to also support dot-notation attributes inside nested objects.This PR requires TypeScript >= 4.1, because it relies on template literal types (see: microsoft/TypeScript#40336)