Comments (6)
Hi! This is is a tricky feature because of the dynamic nature of GROQ. Given the look up attribute[$param]
it's impossible to parse the query correctly without knowing the type of $param. If $param is a string it's an attribute access(object), if it's a number it's an element access(array), and by default it's a filter. Since we rely on the GROQ javascript parser we would need to know the value of $param while parsing, which we don't at the moment
from sanity.
I have the same issue, this could be very useful for field level translations !
from sanity.
Similar to this, the following query generates isCurrentLanguage: unknown
:
"toasts": toasts[]->{"isCurrentLanguage": language == $language, code, title, content},
While if I use a string literal instead, the type is correctly generated as isCurrentLanguage: string
:
"toasts": toasts[]->{"isCurrentLanguage": language == "en", code, title, content},
I also noticed while debugging this query that when using the parent accessor, the type results in Array<never>
:
"toasts": *[_type == "toast" && language == $language && _id in ^.toasts[]{_ref}._ref]{code, heading, content, language}
In all these cases queries correctly work and bring the expected results.
from sanity.
One workaround I tried was to take my initial query with $lang
parameters and create a new "localized query" by replacing all references to [$lang]
with .en
. I thought this would work and then I'd be able to use the type generated for the localized query in the code.
import groq from 'groq';
const fullWidthTextBlockFragment = `
_type == 'module.fullWidthTextBlock' => {
_key,
_type,
"title": title[$lang],
"body": body[$lang],
}
`;
const SanityProductModulesQuery = groq`
*[_type == 'product' && store.slug.current == $handle][0] {
modules[] {
${fullWidthTextBlockFragment},
}
}`;
const LocalizedProductModulesQuery = groq`
${SanityProductModulesQuery.replaceAll('[$lang]', '.en')}
`;
✖ Unsupported expression type: MemberExpression in ../app/groq/product.localized.ts:22:4
⚠ Encountered errors in 1 files while generating types
- I think it would be nice to allow membreExpression and other function calls to be used with sanity codegen
- Even better, it would be awesome if we could pass parameters directly when defining the query (parameters that would be use only for code generation. Something like :
groq(`
*[_type == 'product' && store.slug.current == $handle][0] {
_type == 'module.fullWidthTextBlock' => {
"title": title[$lang],
"body": body[$lang],
}
}`,
{
lang: 'en',
},
);
- Else if we know that all fields of a given objet are the same type, for instance
body : { fr: string; en: string }
I think it would be safe to assume thatbody[$something]
returns a string (or null)
from sanity.
It would be nice being able to at least define parameters in JSDoc (or similar) format for this feature work:
/**
* @param language {string}
*/
const someQuery = groq`
*[_type == 'someType' && language == $language] {...}
`;
This approach might not be enough to unblock the usage of typed fragments though, which would be ideal.
from sanity.
As a workaround, you could try to use select
instead of body[$locale]
export const testQuery = groq`
*[_type == "localizedDocument"][0] {
"body": select(
$locale == "en" => body.en,
$locale == "fr" => body.fr,
)
}
`;
The resulting type of body
is as you expected:
export type TestQueryResult = {
body: string | null;
} | null;
However, this is inconvenient, because you always need to specify this selection. You could create a simple utility that reduces the burden of writing it. However, do not map over your supportedLanguges
to generate these selections. I've found that TypeGen throws an error when you do: ✖ Unsupported expression type: MemberExpression in sanity/schemas/documents/test.ts:48:6 in "sanity/schemas/documents/test.ts"
export const selectLocalizedString = (field: string) =>
`select(
$locale == "en" => ${field}.en,
$locale == "fr" => ${field}.fr,
)`;
// ⚠ Does not work with TypeGen
// export const selectLocalizedString = (field: string) =>
// `select(
// ${supportedLanguages.map((lang) => `$locale == "${lang}" => ${field}.${lang},`).join("\n")}
// )`;
export const testQuery = groq`
*[_type == "localizedDocument"][0] {
"body": ${selectLocalizedString("body")}
}
`;
Here's the full final file I used to reproduce your issue and find a working solution:
import { groq } from "next-sanity";
import { defineField, defineType } from "sanity";
const supportedLanguages = ["en", "fr"] as const;
export const localizedString = defineType({
title: "Localized string",
name: "localizedString",
type: "object",
fields: supportedLanguages.map((lang) => ({
title: lang,
name: lang,
type: "string",
})),
});
export default defineType({
name: "localizedDocument",
title: "Localized Document",
type: "document",
fields: [
defineField({
name: "body",
title: "Body",
type: localizedString.name,
validation: (rule) => rule.required(),
}),
],
});
// export const testQuery = groq`
// *[_type == "localizedDocument"][0] {
// "body": select(
// $locale == "en" => body.en,
// $locale == "fr" => body.fr,
// )
// }
// `;
export const selectLocalizedString = (field: string) =>
`select(
$locale == "en" => ${field}.en,
$locale == "fr" => ${field}.fr,
)`;
// ⚠ Does not work with TypeGen
// export const selectLocalizedString = (field: string) =>
// `select(
// ${supportedLanguages.map((lang) => `$locale == "${lang}" => ${field}.${lang},`).join("\n")}
// )`;
export const testQuery = groq`
*[_type == "localizedDocument"][0] {
"body": ${selectLocalizedString("body")}
}
`;
from sanity.
Related Issues (20)
- Introduce Selective CLI Logging Suppression
- How can I restrict access to resources only through my domain? HOT 2
- TypeGen not generating union type for string array with list option
- can't use `npx @sanity/cli init --template shopify` with the next.js embedded studio option
- On >3.41.0 dragging blocks in PTE gives "Can't upload this file here" error HOT 1
- TypeGen generates Array<never> for query using "in" HOT 1
- TypeGen generates Array<never> for query using chained parent operator
- Hang introduced by #5269, (a0f93cb) (fix included) HOT 3
- Typegen: Can't generate types with conditional values in slice and ordering operations even when the it doesn't effect the type. HOT 3
- All Studio UI menus broken/empty in Dev HOT 1
- Both new and legacy search don't work with documents with a custom title field
- Desk tool crash: editOpsOf does not expect a draft id HOT 1
- throw new Error("'block' type is not defined in this schema (required).");
- Cannot Paste Into Block Content in Mozilla HOT 1
- Provide HTML as a content type for rich text
- The structure tool crashed HOT 3
- connect EHOSTUNREACH 35.241.31.122:443 - sanity service fails (not secure) HOT 2
- TypeScript error importing @sanity/block-tools in Vercel serverless function
- Array: Add `pane` option `options.modal.type`
- TypeGen marks assets of images inside arrays as optional, even with `assetRequired()`
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sanity.