Skip to content

Commit ef560a3

Browse files
authored
feat(typeEvaluator): add support for number + datetime operation (#317)
### TL;DR Adds support for commutative addition between numbers and datetime values. https://linear.app/sanity/issue/CLDX-4468/add-support-for-number-datetime-in-groq-js ### What changed? `number + datetime` is now supported in addition to `datetime + number` ### How to test? Run the new test case that verifies a datetime can be added to a number: ```typescript t.test('number + dateTime', (t) => { const query = `(60 + global::dateTime("2025-03-01T00:00:00Z")) > global::dateTime("2024-03-01T00:00:00Z")` const ast = parse(query) const res = typeEvaluate(ast, schemas) t.same(res, { type: 'union', of: [{type: 'boolean', value: undefined}, {type: 'null'}], }) t.end() }) ``` ### Why make this change? Gradient supports these operations (even though they're not defined in the spec). We should update the spec too, but this change at least gets `groq-js` in line with the actual query engine behaviour, which is what users expect.
1 parent 93e4335 commit ef560a3

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

src/typeEvaluator/typeEvaluate.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {optimizeUnions} from './optimizations'
3434
import {Context, Scope} from './scope'
3535
import {isFuncCall, mapNode, nullUnion, resolveInline} from './typeHelpers'
3636
import {
37-
STRING_TYPE_DATETIME,
3837
type ArrayTypeNode,
3938
type BooleanTypeNode,
4039
type Document,
@@ -44,6 +43,7 @@ import {
4443
type ObjectTypeNode,
4544
type PrimitiveTypeNode,
4645
type Schema,
46+
STRING_TYPE_DATETIME,
4747
type StringTypeNode,
4848
type TypeNode,
4949
type UnionTypeNode,
@@ -621,6 +621,10 @@ function handleOpCallNode(node: OpCallNode, scope: Scope): TypeNode {
621621
if (left.type === 'string' && left[STRING_TYPE_DATETIME] && right.type === 'number') {
622622
return {type: 'string', [STRING_TYPE_DATETIME]: true}
623623
}
624+
// number + datetime -> datetime (commutative)
625+
if (left.type === 'number' && right.type === 'string' && right[STRING_TYPE_DATETIME]) {
626+
return {type: 'string', [STRING_TYPE_DATETIME]: true}
627+
}
624628

625629
if (left.type === 'number' && right.type === 'number') {
626630
return {

test/typeEvaluate.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3746,6 +3746,17 @@ t.test('dateTime with numerical operation', (t) => {
37463746
t.end()
37473747
})
37483748

3749+
t.test('number + dateTime', (t) => {
3750+
const query = `(60 + global::dateTime("2025-03-01T00:00:00Z")) > global::dateTime("2024-03-01T00:00:00Z")`
3751+
const ast = parse(query)
3752+
const res = typeEvaluate(ast, schemas)
3753+
t.same(res, {
3754+
type: 'union',
3755+
of: [{type: 'boolean', value: undefined}, {type: 'null'}],
3756+
})
3757+
t.end()
3758+
})
3759+
37493760
function findSchemaType(name: string): TypeNode {
37503761
const type = schemas.find((s) => s.name === name)
37513762
if (!type) {

0 commit comments

Comments
 (0)