FormidableLabs / FormidableLabs/groqd

Static typing lost when a conditional uses a string template and more than one condition is present

Open
#398 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
293
Forks
15
PR merge metrics
No merged PRs in 30d

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Code of Conduct

- [x] I agree to follow this project's Code of Conduct

### Code Sandbox link

_No response_

### Bug report

```markdown
Have noticed that typing of returned objects is lost if string templating is used in the filter of a conditional statement.

Reporting as a bug since the conditional strings are not strongly typed and the filter used shouldn't impact the eventual types (since it resolves to either true or false, regardless of whether it includes template variables).

`v1.7.1`

Consider these examples:

1. A single template string works as expected:

/**
* @returns ({} | {
* title: string | null;
* })[]
*/
const singleTemplateString = (variable: string) => sanityQuery(q.star
.filterByType('page')
.project(sub => (sub.conditional({
[`[some condition] ${variable}`]: { title: true },
})))
);

2. A variable template string with second static condition casts types to `undefined` (note that the return type is _not_ a union):

/**
* @returns ({} | {
* slug?: undefined;
* title?: undefined;
* })[]
*/
export const withVariableTemplateString = (variable: string) => sanityQuery(q.star
.filterByType('page')
.project(sub => (sub.conditional({
[`[some condition] ${variable}`]: { title: true },
[`[another condition]`]: { slug: true },
})))
);

3. Casting to a string literal no longer resolves to `undefined`

/**
* @returns ({} | {
* slug: SanityTypes.Slug | null;
* } | {
* title: string | null;
* })[]
*/
export const withConstantTemplateString = (variable: string) => sanityQuery(q.star
.filterByType('page')
.project(sub => (sub.conditional({
[`[some condition] ${variable}` as '']: { title: true },
[`[another condition]`]: { slug: true },
})))
);

Note: the return type is a union of each condition, but in practice multiple
conditions can be true at once—and the returned data in real usage reflects this.
I'm using `type-fest`'s `UnionToIntersection` to cast the union to an intersection
to work-around this-but probably warrants a separate issue.
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.