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
CLI Typegen expand references #6327
Comments
Not sure I understand the ask. |
Hello @sgulseth, thank you for your answer and question! Let me elaborate a bit to hopefully clear up my ask a bit. An example of my use case is the following, I am running the query below:
A section could be a e.g. ProgressBar, a Carousel or a Hero. It's basically the blocks that will build the page itself. I am never fetching a singular entity of above, I am always fetching them as part of a page. And therefore I don't have a query that dereferences above entities directly. Below is then what I would like to do to render the sections:
But So basically, I would like to access the complete dereferenced types of all generated types, as above is just an example of where we need access to them in cases where we actually aren't fetching the object itself, but a parent of it. I hope that this made it clearer! If not, or if there is another possible way to achieve above, please do tell me so 🙂 |
What's the result of the Typegen should return all the fields that are available on the actual result |
The first post was basically just a try to give "general example" to describe the issue in "broader" terms 🙂 . But since you asked, here is my very specific one: The result of PAGE_QUERY is basically something like (a bit simplified): This is the generated type of the PAGE_QUERY:
(You may notice that the "Hero section" isn't there, it's because I just wanted to give it as a general example since a Hero is a very common part of a page) |
@sgulseth - Is the use case clearer now? If not, please do tell so and I will try to do my best to expand upon/explain in more detail. |
(Sorry for the late reply here) Yes, I think so. But, if I understand it correctly this is also expected behavior. The types should reflect the raw document stored in Sanity. If you execute a query like *[_type == "page"][0] {
...,
sections[] {
...,
_type == "progressBar" => {
steps[]->
},
_type == "carousel" => {
summaryMicrocopy[]->
}
}
} I agree that it could get a bit "clunky" to write these queries if you have lots of different reference attributes, but improving that should either be a native GROQ feature(We have an issue tracking it here), or a query builder feature. |
The main problem at hand here is the inability to create generic components for objects without direct 1:1 queries. It would be incredibly beneficial and (I assume) low-haul to autogen a lookup table of document For example, consider the following generated schema: // This is an object, not a document
export type InternalLink = {
_type: 'internalLink';
linkTarget?:
| {
_ref: string;
_type: 'reference';
_weak?: boolean;
[internalGroqTypeReferenceTo]?: 'typeA';
}
| {
_ref: string;
_type: 'reference';
_weak?: boolean;
[internalGroqTypeReferenceTo]?: 'typeB';
};
};
// Link text comes from `nameA` field
export type TypeA = {
_id: string;
_type: 'typeA';
slug?: Slug;
nameA?: string;
};
// Link text comes from `nameB` field
export type TypeB = {
_id: string;
_type: 'typeB';
slug?: Slug;
nameB?: string;
}; Some sort of generic link component would look like: export default function InternalLink({ link }: { link: InternalLink }) {
// Opaquely typed linkTarget, e.g. { _type: "reference", [sym]?: "typeA" } | { _type: "reference", [sym]?: "typeB" }
const linkTarget = link.linkTarget;
let text;
// The below switch statement is invalid because the reference hasn't been expanded
switch (linkTarget._type) {
case 'typeA':
text = linkTarget.nameA;
break;
case 'typeB':
text = linkTarget.nameB;
break;
}
text = link.text;
return <a href={`/${linkTarget.slug.current}`}>{text}</a>
} To fix the opaque // Please auto-generate this!
type DoctypeTable = {
typeA: TypeA;
typeB: TypeB;
}
// Exported as strongly-typed generic resolveReference<"typeA" | "typeB">
export function resolveReference<T extends keyof DoctypeTable>(ref: {
_type: 'reference';
[internalGroqTypeReferenceTo]?: T;
}): DoctypeTable[T] {
if (obj._type === 'reference')
throw new Error('Asset reference has not been expanded!');
return obj as unknown as DoctypeTable[T];
} Meaning our generic link component could now convert references into their referenced types as well as - // Opaquely typed linkTarget, e.g. { _type: "reference", [sym]?: "typeA" } | { _type: "reference", [sym]?: "typeB" }
- const linkTarget = link.linkTarget;
+ // Correctly typed linkTarget, e.g. TypeA | TypeB
+ const linkTarget = resolveReference(link.linkTarget); If |
(It's okay!) Thank you for your answer sgulseth. I do realize that this is probably the "expected behavior" as of right now, but this issue is more of a feature request rather than a bug report. While your example query does expand/de-reference the type result of the specific "page query" correctly, it still doesn't fulfill the desired behavior that we're asking for. I am never explictly fetching only ProgressBar, and therefore I can't access a de-referenced version of the type ProgressBar, making it impossible to create a generic component (as evankirkiles stated) for it. I don't think that GROQ has to be changed to give the possibility of implementing a type-generation that (has the possibility to) expand/de-reference relations. evankirkiles gives a good example of a possible solution above. |
We would very much like some way of resolving all the references during type generation. We have a pretty complex schema setup with a lot of references. For context, the generated types file is well over 9000 lines long. Currently we are using the old archived Being able to generate some form of lookup table, or using generics like the old plugin does is basically required for us to move over to TypeGen. You don't need to have that many types for it to be unsustainable to manage manually, and we have a lot of them. |
@sgulseth , do you have any kind of update here? It looks like we are quite a few that would very much like this functionality added to the sanity typegen. |
Hi @nikmatswace - we are in the process of scoping the next work for typegen. However, we should have some outlines shortly. Would returning a type like:
Be better than having a map? Trying to think of pros/cons, and we don't want to be stuck in a corner 🤔 |
I think it would be step in the right direction! With the above implementation and some custom code to resolve the internalGroqTypeReference I think it would be possible to achieve the desired behavior. But I would have to spend some time to play around with it to verify it. My primary wish would be to be able to generate the types and add some kind of flag to automatically dereference any references in the generated types though. Meaning something like:
|
The goal with typegen is to able to introspect groq queries and return a conforming type for what the query would return. Automatically dereferencing the types would break that goal. |
Is your feature request related to a problem? Please describe.
When generating types you only get an "internalGroqTypeReferenceTo" a related schema.
This means that you can't access the actual properties on an indiviual "step", which becomes troublesome when you have several references to other schemas or some kind of multi-level-reference structure (e.g. I have a Page with a Progress bar that has Progress bar steps).
Describe the solution you'd like
It would be great if we during the type generation could define if we wanted all/some "internalGroqTypeReferences" expanded. Perhaps either via the typegen config or some kind of flag on the schema itself.
The result after such an expansion could be something like:
Describe alternatives you've considered
I've considered creating a "dummy query" that explicitly expands the type but isn't used anywhere, however I don't think that's a very clean solution. I've also tried to alter the main query that contains multi-level-references to try and get the query-typegen to expand the "deeper levels of nesting" but with no success.
Additional context
Typegen is a super helpful feature, and the current state is a very promising! I do however think that there is room for some improvement, an this would bring it a big step forward!
The text was updated successfully, but these errors were encountered: