-
Notifications
You must be signed in to change notification settings - Fork 2k
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: depth
generic, fully type safe result types for relationships and joins
#9782
base: main
Are you sure you want to change the base?
Conversation
I'd be curious if we would benefit from introducing a type assertions tool like tsd or tstyche. |
As proposed here #9782 (comment) with additional testing of our types we can be more sure that we don't break them between updates. This PR already adds types testing for most Local API methods https://github.com/payloadcms/payload/blob/6beb921c2e232ab4edfa38c480af40a1bec1106e/test/types/types.spec.ts but new tests for types can be easily added, either to that same file or you can create `types.spec.ts` in any other test folder. The new test folder uses `strict: true` to ensure our types do not break with it. --------- Co-authored-by: Tom Mrazauskas <[email protected]>
a245bf7
to
1af8521
Compare
We have now type assertions here - https://github.com/payloadcms/payload/pull/9782/files#diff-8dec54cdc3beba0979d4e6eceb4130340bd2ee3bc91f1e779145baaeae8ea440 works perfectly! |
8ec299c
to
e9979f9
Compare
5725d71
to
ad5e9d5
Compare
…for groups / tabs / arrrays/ blocks but keep for polymorphic relationships
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'll need more time to test this on a canary version with an actual project.
| **`autoGenerate`** | By default, Payload will auto-generate TypeScript interfaces for all collections and globals that your config defines. Opt out by setting `typescript.autoGenerate: false`. [More details](../typescript/overview). | | ||
| **`declare`** | By default, Payload adds a `declare` block to your generated types, which makes sure that Payload uses your generated types for all Local API methods. Opt out by setting `typescript.declare: false`. | | ||
| **`outputFile`** | Control the output path and filename of Payload's auto-generated types by defining the `typescript.outputFile` property to a full, absolute path. | | ||
| **`typeSafeDepth`** | Enable better result types for relationships depending on `depth`, disabled by default. [More Details](../queries/depth#type-safe-relationship-types-with-depth). | |
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.
We should enable this as the default option for all templates/examples.
This feature allows you to have fully type safe results for relationship / joins fields depending on
depth
. Currently this is opt-in withtypescript.typeSafeDepth: true
property, as it may break existing types. Meaning without enabling it - there's no any effect on your existing project. Discussion - #8229For example, with the given config:
Let's try to fetch some movies using the Local API:
Without specifying
depth
, the result type for each movie isApplyDepth<Movie, 2>
: (FromdefaultDepth
)movie.author
isApplyDepth<Author, 1>
, without this feature it'd have been annoyingstring | Author
:movie.author.books
isApplyDepth<Book, 0>[]
because of thehasMany
relationship:But then, if we try to access
movie.author.books[0].relatedMovie
we getstring
which is exactly what we expect fromdepth: 2
:However, with
depth: 3
we getrelatedMovie: ApplyDepth<Movie, 0>
:Now, let's try to specify
depth: 0
:The result type is
ApplyDepth<Movie, 0>
andmovie.author
isstring
:This also works for join fields as well.
Challenges:
__collection
property (iftypescript.typeSafeDepth
for collection generated types which the generic uses.payload/test/relationships/payload-types.ts
Line 127 in a245bf7
There are hacks https://softwaremill.com/implementing-advanced-type-level-arithmetic-in-typescript-part-1/ that potentially may screw Typescript Server performance, so in this PR I went with even better approach to generate types for
depth
specifically:payload/test/relationships/payload-types.ts
Lines 73 to 80 in a245bf7
depth.default
we use whendepth
isn't passed,allowed
- an enum of alloweddepth
values. For example we can't pass11
:And
depth.decremented
is used for internal typescript purposes which allows us to easily decrement depth for typescript:payload/packages/payload/src/index.ts
Lines 227 to 233 in a245bf7
For example
DecrementDepth<2>
- result1
.