diff --git a/src/typeEvaluator/functions.ts b/src/typeEvaluator/functions.ts index 5d6f1e1..daaae63 100644 --- a/src/typeEvaluator/functions.ts +++ b/src/typeEvaluator/functions.ts @@ -2,7 +2,7 @@ import type {FuncCallNode} from '../nodeTypes' import {Scope} from './scope' import {walk} from './typeEvaluate' -import {mapConcrete} from './typeHelpers' +import {mapConcrete, nullUnion} from './typeHelpers' import type {NullTypeNode, TypeNode} from './types' function unionWithoutNull(unionTypeNode: TypeNode): TypeNode { @@ -148,6 +148,18 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { }) } + case 'global.dateTime': { + const arg = walk({node: node.args[0], scope}) + + return mapConcrete(arg, scope, (arg) => { + if (arg.type === 'string') { + return nullUnion({type: 'string'}) // we don't know wether the string is a valid date or not, so we return a [null, string]-union + } + + return {type: 'null'} satisfies NullTypeNode + }) + } + case 'global.references': { return {type: 'boolean'} } diff --git a/test/typeEvaluate.test.ts b/test/typeEvaluate.test.ts index f014e0c..f5da3fb 100644 --- a/test/typeEvaluate.test.ts +++ b/test/typeEvaluate.test.ts @@ -2230,6 +2230,57 @@ t.test('function: global::string', (t) => { t.end() }) +t.test('function: global::dateTime', (t) => { + const query = `*[_type == "author"] { + "string": dateTime(name), + "constant": dateTime("const"), + "number": dateTime(age), + "boolean": dateTime(true), + "object": dateTime(object) + }` + const ast = parse(query) + const res = typeEvaluate(ast, schemas) + t.strictSame(res, { + type: 'array', + of: { + type: 'object', + attributes: { + string: { + type: 'objectAttribute', + value: nullUnion({ + type: 'string', + }), + }, + constant: { + type: 'objectAttribute', + value: nullUnion({ + type: 'string', + }), + }, + number: { + type: 'objectAttribute', + value: { + type: 'null', + }, + }, + boolean: { + type: 'objectAttribute', + value: { + type: 'null', + }, + }, + object: { + type: 'objectAttribute', + value: { + type: 'null', + }, + }, + }, + }, + }) + t.end() +}) + t.test('function: global::upper', (t) => { const query = `*[_type == "author"] { "_type": upper(_type), diff --git a/test/typeEvaluateCompare.test.ts b/test/typeEvaluateCompare.test.ts index 6e94395..af66d33 100644 --- a/test/typeEvaluateCompare.test.ts +++ b/test/typeEvaluateCompare.test.ts @@ -424,6 +424,7 @@ const unaryFunctionTests: {namespace: string; funcName: string}[] = [ {namespace: 'math', funcName: 'avg'}, {namespace: 'array', funcName: 'compact'}, {namespace: 'array', funcName: 'unique'}, + {namespace: 'global', funcName: 'dateTime'}, ] for (const {namespace, funcName} of unaryFunctionTests) {