Open hasezoey opened 2 years ago
just noticed that #10180 is a similar Issue, should that one be closed in favor of this (or vise versa)?
I'm really wary of doing this because I imagine it'll be horrifically slow and cause a lot of impossible to debug "Type instantiation is excessively deep and possibly infinite" type errors.
I've tried adding the following to query.d.ts
:
type PathsToStringProps<T> = T extends string
? []
: {
[K in Extract<keyof T, string>]: [K, ...PathsToStringProps<T[K]>];
}[Extract<keyof T, string>];
type Join<T extends string[], D extends string> = T extends []
? never
: T extends [infer F]
? F
: T extends [infer F, ...infer R]
? F extends string
? `${F}${D}${Join<Extract<R, string[]>, D>}`
: never
: string;
type _FilterQuery<T> = {
[P in keyof T]?: Condition<T[P]>;
} & RootQuerySelector<T>;
/**
* Filter query to select the documents that match the query
* @example
* ```js
* { age: { $gte: 30 } }
* ```
*/
type FilterQuery<T> = _FilterQuery<T> & Join<PathsToStringProps<T>, '.'>;
And I'm getting the following:
../mongoose/types/query.d.ts:34:48 - error TS2321: Excessive stack depth comparing types 'PathsToStringProps<T>' and 'string[]'.
34 type FilterQuery<T> = _FilterQuery<T> & Join<PathsToStringProps<T>, '.'>;
~~~~~~~~~~~~~~~~~~~~~
Found 1 error in ../mongoose/types/query.d.ts:34
Haven't been able to find a workaround. Any suggestions @hasezoey ?
Haven't been able to find a workaround. Any suggestions @hasezoey ?
no i dont have any solutions, and yes it would cause may "too deep" errors, because that is basically what this approach is "meant" to do, the only ways i could see are:
i had just noted it here because it was now possible and mongoose already uses it in places at runtime but didnt have it in types
I stumbled upon this myself a couple of days ago and came up with a solution (whose performance is questionable but perhaps a bit better): https://tsplay.dev/wO2xRW
Hey, I came up with a solution, as seen above ^
This solution is very performant – according to my tests, the compilation and emit of the type file and a file that uses this type take around 20ms.
The implementation makes FilterQuery
more strict by overriding the ApplyBasicQueryCasting
to avoid the unnecessary any
in the union.
The two main types are DeepNestedAccess
and RecursiveFieldsOfObject
.
DeepNestedAccess
is a way to access elements in objects and arrays via dot-notation strings (e.g. 'array.0.field' will actually access the 'field' element in the first element of the array).
RecursiveFieldsOfObject
gets all the paths and nested paths of an object, including arrays.
I'll provide some screenshots and sources for my tests and open a PR in a sec
Unfortunately @PCOffline 's solution doesn't work too well, I tried it for #14615 but unfortunately results in an infinite type instantiation error in automatic schema inference.
../mongoose/types/index.d.ts:90:3 - error TS2589: Type instantiation is excessively deep and possibly infinite.
90 HydratedDocument<
~~~~~~~~~~~~~~~~~
91 InferSchemaType<TSchema>,
~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
93 ObtainSchemaGeneric<TSchema, 'TQueryHelpers'>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
94 >,
~~~
Realistically, I don't think we can support this unless TypeScript has some sort of way to limit the depth of the recursion or avoiding infinite recursion.
Prerequisites
Issue
Currently Query's do not have dotted path suggestions, but would be possible with current typescript.
See This Stackoverflow Answer
TL;DR: a simple example of what the stackoverflow answer has does (note: the types are directly copied from the answer)
Disclaimer: i am by no means a expert at complex typescript types, i also have no clue about the effect on types performance this would bring