-
Notifications
You must be signed in to change notification settings - Fork 3.2k
feat: depth generic, fully type safe result types for relationships and joins
#9782
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
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 <tom@mrazauskas.de>
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
DanRibbens
left a comment
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.
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.
@DanRibbens and @r1tsuu Would it be possible to mark this feature as experimental, and include it in a release? That way people can start using it if they opt into experimental usage, and collect feedback from real-world usage.
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'd be happy to try this out on our project if it ended up behind an experimental flag.
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 think it'd be reasonable, but we shouldn't enable it for templates/examples then at the start, but rather after some feedback on this feature.
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.
@DanRibbens What are your thoughts on this?
|
@r1tsuu @DanRibbens Sorry for bothering you guys once again, but this feature is absolutely mindblowing. Is there anything I can do to help this feature get shipped in the next update? |
You're not bothering us at all. Thank you for the nudge. I will try and make more time for this soon. |
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 <tom@mrazauskas.de>
|
Fantastic feature, excited to see it, great job Payload team |
71c41ba to
cd9262e
Compare
|
@r1tsuu Is it possible to somehow start using this inside a project? If not, pkg.pr.new might be interesting so the community can start testing these types of changes |
|
@DanRibbens By any chance had time to look into this? |
|
This feature would be massively helpful! 🙏 |
|
Any updates on this? |
|
I’m super stoked for this as well and can’t wait for this feature to be ready. This would dramatically improve my code quality! |
|
@ericwaetke Agree! |
I’ve got a function like this, pretty sure it’ll work most of the time async function fetchOrReturnRealValue<T extends keyof Config['collections']>(
item: number | Config['collections'][T],
collection: T
): Promise<Config['collections'][T]> {
if (typeof item === "number") {
const payload = await getPayload()
return await payload.findByID({
collection,
id: item
}) as Config['collections'][T]
} else {
return item as Config['collections'][T]
}
} |
|
@r1tsuu we should revisit this one. |
|
Wondering if this could get a follow-up, this PR increases DX by a lot! |
|
I wish this one to be implemented. This is really annoying in terms of DX to have a |
|
@r1tsuu does this PR make the |
This feature allows you to have fully type safe results for relationship / joins fields depending on
depth. Currently this is opt-in withtypescript.typeSafeDepth: trueproperty, 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.authorisApplyDepth<Author, 1>, without this feature it'd have been annoyingstring | Author:movie.author.booksisApplyDepth<Book, 0>[]because of thehasManyrelationship:But then, if we try to access


movie.author.books[0].relatedMoviewe getstringwhich is exactly what we expect fromdepth: 2:However, with
depth: 3we getrelatedMovie: ApplyDepth<Movie, 0>:Now, let's try to specify

depth: 0:The result type is
ApplyDepth<Movie, 0>andmovie.authorisstring:This also works for join fields as well.
Challenges:
__collectionproperty (iftypescript.typeSafeDepthfor 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
depthspecifically:payload/test/relationships/payload-types.ts
Lines 73 to 80 in a245bf7
depth.defaultwe use whendepthisn't passed,allowed- an enum of alloweddepthvalues. For example we can't pass11:And
depth.decrementedis 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.