[[test]]
name = "merge: string | null"
expression = "flag ? name : null"
input = '{"Object": {"flag": "Bool", "name": "String"}}'
[test.loose]
return_type = '{"Nullable": "String"}'
[test.strict]
return_type = '{"Nullable": "String"}'
[[test]]
name = "merge: null | string"
expression = "flag ? null : name"
input = '{"Object": {"flag": "Bool", "name": "String"}}'
[test.loose]
return_type = '{"Nullable": "String"}'
[test.strict]
return_type = '{"Nullable": "String"}'
[[test]]
name = "merge: number | null"
expression = "flag ? age : null"
input = '{"Object": {"flag": "Bool", "age": "Number"}}'
[test.loose]
return_type = '{"Nullable": "Number"}'
[test.strict]
return_type = '{"Nullable": "Number"}'
[[test]]
name = "merge: null | number"
expression = "flag ? null : age"
input = '{"Object": {"flag": "Bool", "age": "Number"}}'
[test.loose]
return_type = '{"Nullable": "Number"}'
[test.strict]
return_type = '{"Nullable": "Number"}'
[[test]]
name = "merge: bool | null"
expression = "flag ? active : null"
input = '{"Object": {"flag": "Bool", "active": "Bool"}}'
[test.loose]
return_type = '{"Nullable": "Bool"}'
[test.strict]
return_type = '{"Nullable": "Bool"}'
[[test]]
name = "merge: date | null"
expression = "flag ? d : null"
input = '{"Object": {"flag": "Bool", "d": "Date"}}'
[test.loose]
return_type = '{"Nullable": "Date"}'
[test.strict]
return_type = '{"Nullable": "Date"}'
[[test]]
name = "merge: null | null => Null"
expression = "flag ? null : null"
input = '{"Object": {"flag": "Bool"}}'
[test.loose]
return_type = '"Null"'
[test.strict]
return_type = '"Null"'
[[test]]
name = "merge: same type no nullable"
expression = "flag ? a : b"
input = '{"Object": {"flag": "Bool", "a": "String", "b": "String"}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '"String"'
[[test]]
name = "merge: same number no nullable"
expression = "flag ? a : b"
input = '{"Object": {"flag": "Bool", "a": "Number", "b": "Number"}}'
[test.loose]
return_type = '"Number"'
[test.strict]
return_type = '"Number"'
[[test]]
name = "merge: same bool no nullable"
expression = "flag ? a : b"
input = '{"Object": {"flag": "Bool", "a": "Bool", "b": "Bool"}}'
[test.loose]
return_type = '"Bool"'
[test.strict]
return_type = '"Bool"'
[[test]]
name = "merge: const | null => Nullable(Const)"
expression = "flag ? 'hello' : null"
input = '{"Object": {"flag": "Bool"}}'
[test.loose]
return_type = '{"Nullable": {"Const": "hello"}}'
[test.strict]
return_type = '{"Nullable": {"Const": "hello"}}'
[[test]]
name = "merge: null | const => Nullable(Const)"
expression = "flag ? null : 'world'"
input = '{"Object": {"flag": "Bool"}}'
[test.loose]
return_type = '{"Nullable": {"Const": "world"}}'
[test.strict]
return_type = '{"Nullable": {"Const": "world"}}'
[[test]]
name = "merge: const | const => Enum"
expression = "flag ? 'hello' : 'world'"
input = '{"Object": {"flag": "Bool"}}'
[test.loose]
return_type = '{"Enum": [null, ["hello", "world"]]}'
[test.strict]
return_type = '{"Enum": [null, ["hello", "world"]]}'
[[test]]
name = "merge: same const => Const"
expression = "flag ? 'same' : 'same'"
input = '{"Object": {"flag": "Bool"}}'
[test.loose]
return_type = '{"Const": "same"}'
[test.strict]
return_type = '{"Const": "same"}'
[[test]]
name = "merge: const | string => String"
expression = "flag ? 'literal' : name"
input = '{"Object": {"flag": "Bool", "name": "String"}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '"String"'
[[test]]
name = "merge: string | const => String"
expression = "flag ? name : 'literal'"
input = '{"Object": {"flag": "Bool", "name": "String"}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '"String"'
[[test]]
name = "merge: string | number => Any"
expression = "flag ? name : age"
input = '{"Object": {"flag": "Bool", "name": "String", "age": "Number"}}'
[test.loose]
return_type = '"Any"'
[test.strict]
return_type = '"Any"'
[[test]]
name = "merge: bool | string => Any"
expression = "flag ? active : name"
input = '{"Object": {"flag": "Bool", "active": "Bool", "name": "String"}}'
[test.loose]
return_type = '"Any"'
[test.strict]
return_type = '"Any"'
[[test]]
name = "merge: number | bool => Any"
expression = "flag ? age : active"
input = '{"Object": {"flag": "Bool", "age": "Number", "active": "Bool"}}'
[test.loose]
return_type = '"Any"'
[test.strict]
return_type = '"Any"'
[[test]]
name = "merge: any | T => Any"
expression = "flag ? x : name"
input = '{"Object": {"flag": "Bool", "x": "Any", "name": "String"}}'
[test.loose]
return_type = '"Any"'
[test.strict]
return_type = '"Any"'
[[test]]
name = "merge: T | any => Any"
expression = "flag ? name : x"
input = '{"Object": {"flag": "Bool", "name": "String", "x": "Any"}}'
[test.loose]
return_type = '"Any"'
[test.strict]
return_type = '"Any"'
[[test]]
name = "merge: Nullable(String) | Nullable(String)"
expression = "flag ? a : b"
input = '{"Object": {"flag": "Bool", "a": {"Nullable": "String"}, "b": {"Nullable": "String"}}}'
[test.loose]
return_type = '{"Nullable": "String"}'
[test.strict]
return_type = '{"Nullable": "String"}'
[[test]]
name = "merge: Nullable(Number) | Number"
expression = "flag ? a : b"
input = '{"Object": {"flag": "Bool", "a": {"Nullable": "Number"}, "b": "Number"}}'
[test.loose]
return_type = '{"Nullable": "Number"}'
[test.strict]
return_type = '{"Nullable": "Number"}'
[[test]]
name = "merge: Number | Nullable(Number)"
expression = "flag ? a : b"
input = '{"Object": {"flag": "Bool", "a": "Number", "b": {"Nullable": "Number"}}}'
[test.loose]
return_type = '{"Nullable": "Number"}'
[test.strict]
return_type = '{"Nullable": "Number"}'
[[test]]
name = "merge: Nullable(String) | null"
expression = "flag ? a : null"
input = '{"Object": {"flag": "Bool", "a": {"Nullable": "String"}}}'
[test.loose]
return_type = '{"Nullable": "String"}'
[test.strict]
return_type = '{"Nullable": "String"}'
[[test]]
name = "merge: null | Nullable(Bool)"
expression = "flag ? null : a"
input = '{"Object": {"flag": "Bool", "a": {"Nullable": "Bool"}}}'
[test.loose]
return_type = '{"Nullable": "Bool"}'
[test.strict]
return_type = '{"Nullable": "Bool"}'
[[test]]
name = "merge: Nullable(String) | Number => Any (incompatible inner)"
expression = "flag ? a : b"
input = '{"Object": {"flag": "Bool", "a": {"Nullable": "String"}, "b": "Number"}}'
[test.loose]
return_type = '"Any"'
[test.strict]
return_type = '"Any"'
[[test]]
name = "merge: Any | Nullable(String) => Any"
expression = "flag ? a : b"
input = '{"Object": {"flag": "Bool", "a": "Any", "b": {"Nullable": "String"}}}'
[test.loose]
return_type = '"Any"'
[test.strict]
return_type = '"Any"'
[[test]]
name = "merge: array | null => Nullable(Array)"
expression = "flag ? items : null"
input = '{"Object": {"flag": "Bool", "items": {"Array": "Number"}}}'
[test.loose]
return_type = '{"Nullable": {"Array": "Number"}}'
[test.strict]
return_type = '{"Nullable": {"Array": "Number"}}'
[[test]]
name = "merge: array | array => Array"
expression = "flag ? a : b"
input = '{"Object": {"flag": "Bool", "a": {"Array": "String"}, "b": {"Array": "String"}}}'
[test.loose]
return_type = '{"Array": "String"}'
[test.strict]
return_type = '{"Array": "String"}'
[[test]]
name = "member: nullable object property"
expression = "user.name"
input = '{"Object": {"user": {"Nullable": {"Object": {"name": "String"}}}}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '{"Nullable": "String"}'
[[test]]
name = "member: nullable object nested"
expression = "user.address"
input = '{"Object": {"user": {"Nullable": {"Object": {"address": {"Object": {"city": "String"}}}}}}}'
[test.loose]
return_type = '{"Object": {"city": "String"}}'
[test.strict]
return_type = '{"Nullable": {"Object": {"city": "String"}}}'
[[test]]
name = "member: nullable object nested chain"
expression = "user.address.city"
input = '{"Object": {"user": {"Nullable": {"Object": {"address": {"Object": {"city": "String"}}}}}}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '{"Nullable": "String"}'
[[test]]
name = "member: nullable array index"
expression = "items[0]"
input = '{"Object": {"items": {"Nullable": {"Array": "Number"}}}}'
[test.loose]
return_type = '"Number"'
[test.strict]
return_type = '{"Nullable": "Number"}'
[[test]]
name = "member: array index introduces nullable in strict"
expression = "items[0]"
input = '{"Object": {"items": {"Array": "Number"}}}'
[test.loose]
return_type = '"Number"'
[test.strict]
return_type = '{"Nullable": "Number"}'
[[test]]
name = "member: indexed property is nullable in strict"
expression = "companies[0].revenue"
input = '{"Object": {"companies": {"Array": {"Object": {"revenue": "Number"}}}}}'
[test.loose]
return_type = '"Number"'
[test.strict]
return_type = '{"Nullable": "Number"}'
[[test]]
name = "member: coalesce recovers from nullable index"
expression = "companies[0].revenue ?? 0"
input = '{"Object": {"companies": {"Array": {"Object": {"revenue": "Number"}}}}}'
[test.loose]
return_type = '"Number"'
[test.strict]
return_type = '"Number"'
[[test]]
name = "member: nullable object unknown key"
expression = "user.unknown"
input = '{"Object": {"user": {"Nullable": {"Object": {"name": "String"}}}}}'
[test.loose]
return_type = '"Any"'
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "member: null type returns Null"
expression = "x.foo"
input = '{"Object": {"x": "Null"}}'
[test.loose]
return_type = '"Null"'
[test.strict]
return_type = '"Null"'
[[test]]
name = "coalesce: Nullable(String) ?? const"
expression = "name ?? 'default'"
input = '{"Object": {"name": {"Nullable": "String"}}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '"String"'
[[test]]
name = "coalesce: Nullable(Number) ?? number"
expression = "val ?? 0"
input = '{"Object": {"val": {"Nullable": "Number"}}}'
[test.loose]
return_type = '"Number"'
[test.strict]
return_type = '"Number"'
[[test]]
name = "coalesce: Null ?? number"
expression = "x ?? 42"
input = '{"Object": {"x": "Null"}}'
[test.loose]
return_type = '"Number"'
[test.strict]
return_type = '"Number"'
[[test]]
name = "coalesce: non-nullable passes through"
expression = "name ?? 'fallback'"
input = '{"Object": {"name": "String"}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '"String"'
[[test]]
name = "coalesce: Nullable(Const) ?? const => Enum"
expression = "x ?? 'other'"
input = '{"Object": {"x": {"Nullable": {"Const": "hello"}}}}'
[test.loose]
return_type = '{"Enum": [null, ["hello", "other"]]}'
[test.strict]
return_type = '{"Enum": [null, ["hello", "other"]]}'
[[test]]
name = "coalesce: Nullable(Bool) ?? bool"
expression = "active ?? false"
input = '{"Object": {"active": {"Nullable": "Bool"}}}'
[test.loose]
return_type = '"Bool"'
[test.strict]
return_type = '"Bool"'
[[test]]
name = "coalesce: Any ?? string => Any"
expression = "x ?? 'hi'"
input = '{"Object": {"x": "Any"}}'
[test.loose]
return_type = '"Any"'
[test.strict]
return_type = '"Any"'
[[test]]
name = "compare: nullable == literal"
expression = "val == 5"
input = '{"Object": {"val": {"Nullable": "Number"}}}'
[test.loose]
return_type = '"Bool"'
[test.strict]
return_type = '"Bool"'
[[test]]
name = "compare: nullable != literal"
expression = "val != 5"
input = '{"Object": {"val": {"Nullable": "Number"}}}'
[test.loose]
return_type = '"Bool"'
[test.strict]
return_type = '"Bool"'
[[test]]
name = "compare: nullable == null"
expression = "val == null"
input = '{"Object": {"val": {"Nullable": "Number"}}}'
[test.loose]
return_type = '"Bool"'
[test.strict]
return_type = '"Bool"'
[[test]]
name = "compare: nullable != null"
expression = "val != null"
input = '{"Object": {"val": {"Nullable": "Number"}}}'
[test.loose]
return_type = '"Bool"'
[test.strict]
return_type = '"Bool"'
[[test]]
name = "compare: nullable string == const"
expression = "name == 'hello'"
input = '{"Object": {"name": {"Nullable": "String"}}}'
[test.loose]
return_type = '"Bool"'
[test.strict]
return_type = '"Bool"'
[[test]]
name = "compare: nullable < number => error"
expression = "val < 10"
input = '{"Object": {"val": {"Nullable": "Number"}}}'
[test.loose]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "compare: nullable > number => error"
expression = "val > 0"
input = '{"Object": {"val": {"Nullable": "Number"}}}'
[test.loose]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "arith: nullable + number => error"
expression = "val + 1"
input = '{"Object": {"val": {"Nullable": "Number"}}}'
[test.loose]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "arith: nullable - number => error"
expression = "val - 1"
input = '{"Object": {"val": {"Nullable": "Number"}}}'
[test.loose]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "arith: nullable * number => error"
expression = "val * 2"
input = '{"Object": {"val": {"Nullable": "Number"}}}'
[test.loose]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "arith: nullable string + string => error"
expression = "name + ' world'"
input = '{"Object": {"name": {"Nullable": "String"}}}'
[test.loose]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "logical: nullable and bool => error"
expression = "a and b"
input = '{"Object": {"a": {"Nullable": "Bool"}, "b": "Bool"}}'
[test.loose]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "logical: nullable or bool => error"
expression = "a or b"
input = '{"Object": {"a": {"Nullable": "Bool"}, "b": "Bool"}}'
[test.loose]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "logical: not nullable => error"
expression = "not a"
input = '{"Object": {"a": {"Nullable": "Bool"}}}'
[test.loose]
return_type = '"Bool"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Bool"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "edge: deeply nested ternary with nulls"
expression = "a ? (b ? x : null) : null"
input = '{"Object": {"a": "Bool", "b": "Bool", "x": "Number"}}'
[test.loose]
return_type = '{"Nullable": "Number"}'
[test.strict]
return_type = '{"Nullable": "Number"}'
[[test]]
name = "edge: chained coalesce"
expression = "a ?? b ?? 'default'"
input = '{"Object": {"a": {"Nullable": "String"}, "b": {"Nullable": "String"}}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '"String"'
[[test]]
name = "edge: coalesce then member"
expression = "(user ?? fallback).name"
input = '{"Object": {"user": {"Nullable": {"Object": {"name": "String"}}}, "fallback": {"Object": {"name": "String"}}}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '"String"'
[[test]]
name = "edge: ternary producing Nullable then coalesce"
expression = "(flag ? name : null) ?? 'none'"
input = '{"Object": {"flag": "Bool", "name": "String"}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '"String"'
[[test]]
name = "edge: ternary with Any branch"
expression = "flag ? x : null"
input = '{"Object": {"flag": "Bool", "x": "Any"}}'
[test.loose]
return_type = '"Any"'
[test.strict]
return_type = '"Any"'
[[test]]
name = "edge: double nullable merge stays single"
expression = "a ? (b ? x : null) : null"
input = '{"Object": {"a": "Bool", "b": "Bool", "x": "String"}}'
[test.loose]
return_type = '{"Nullable": "String"}'
[test.strict]
return_type = '{"Nullable": "String"}'
[[test]]
name = "edge: Nullable(Nullable) does not nest from merge"
expression = "flag ? a : null"
input = '{"Object": {"flag": "Bool", "a": {"Nullable": "String"}}}'
[test.loose]
return_type = '{"Nullable": "String"}'
[test.strict]
return_type = '{"Nullable": "String"}'
[[test]]
name = "edge: in operator with nullable array => error"
expression = "3 in items"
input = '{"Object": {"items": {"Nullable": {"Array": "Number"}}}}'
[test.loose]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "edge: not in with nullable array => error"
expression = "3 not in items"
input = '{"Object": {"items": {"Nullable": {"Array": "Number"}}}}'
[test.loose]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[test.strict]
return_type = '"Any"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "edge: in with non-nullable array works"
expression = "3 in items"
input = '{"Object": {"items": {"Array": "Number"}}}'
[test.loose]
return_type = '"Bool"'
[test.strict]
return_type = '"Bool"'
[[test]]
name = "closure: map over nullable array"
expression = "map(items as item, item.price)"
input = '{"Object": {"items": {"Nullable": {"Array": {"Object": {"price": "Number"}}}}}}'
[test.loose]
return_type = '{"Array": "Number"}'
[test.strict]
return_type = '{"Array": "Number"}'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "closure: map over nullable array with fallback"
expression = "map(items ?? [], #.price)"
input = '{"Object": {"items": {"Nullable": {"Array": {"Object": {"price": "Number"}}}}}}'
[test.loose]
return_type = '{"Array": "Number"}'
[test.strict]
return_type = '{"Array": "Number"}'
[[test]]
name = "closure: map unknown property on nullable array (strict error)"
expression = "map(items as item, item.unknown)"
input = '{"Object": {"items": {"Nullable": {"Array": {"Object": {"price": "Number"}}}}}}'
[test.loose]
return_type = '{"Array": "Any"}'
[test.strict]
return_type = '{"Array": "Any"}'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "closure: filter over nullable array"
expression = "filter(items as item, item.active)"
input = '{"Object": {"items": {"Nullable": {"Array": {"Object": {"active": "Bool"}}}}}}'
[test.loose]
return_type = '{"Nullable": {"Array": {"Object": {"active": "Bool"}}}}'
[test.strict]
return_type = '{"Nullable": {"Array": {"Object": {"active": "Bool"}}}}'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "closure: some over nullable array"
expression = "some(items as item, item.active)"
input = '{"Object": {"items": {"Nullable": {"Array": {"Object": {"active": "Bool"}}}}}}'
[test.loose]
return_type = '"Bool"'
[test.strict]
return_type = '"Bool"'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "closure: map over non-nullable array valid member"
expression = "map(companies as c, c.name)"
input = '{"Object": {"companies": {"Array": {"Object": {"name": "String", "revenue": "Number"}}}}}'
[test.loose]
return_type = '{"Array": "String"}'
[test.strict]
return_type = '{"Array": "String"}'
[[test]]
name = "closure: map over non-nullable array unknown member (strict error)"
expression = "map(companies as c, c.unknownProperty)"
input = '{"Object": {"companies": {"Array": {"Object": {"name": "String", "revenue": "Number"}}}}}'
[test.loose]
return_type = '{"Array": "Any"}'
[test.strict]
return_type = '{"Array": "Any"}'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "closure: callback ref on nullable array"
expression = "map(items, #.price)"
input = '{"Object": {"items": {"Nullable": {"Array": {"Object": {"price": "Number"}}}}}}'
[test.loose]
return_type = '{"Array": "Number"}'
[test.strict]
return_type = '{"Array": "Number"}'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "closure: callback ref unknown property (strict error)"
expression = "map(items, #.unknown)"
input = '{"Object": {"items": {"Nullable": {"Array": {"Object": {"price": "Number"}}}}}}'
[test.loose]
return_type = '{"Array": "Any"}'
[test.strict]
return_type = '{"Array": "Any"}'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "closure: nested nullable array closure"
expression = "map(groups as g, map(g.items as item, item.value))"
input = '{"Object": {"groups": {"Nullable": {"Array": {"Object": {"items": {"Array": {"Object": {"value": "Number"}}}}}}}}}'
[test.loose]
return_type = '{"Array": {"Array": "Number"}}'
[test.strict]
return_type = '{"Array": {"Array": "Number"}}'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "closure: nested nullable array closure with fallback"
expression = "map(groups ?? [], map(#.items, #.value))"
input = '{"Object": {"groups": {"Nullable": {"Array": {"Object": {"items": {"Array": {"Object": {"value": "Number"}}}}}}}}}'
[test.loose]
return_type = '{"Array": {"Array": "Number"}}'
[test.strict]
return_type = '{"Array": {"Array": "Number"}}'
[[test]]
name = "string number index"
expression = "name[0]"
input = '{"name": "hello"}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '{"Nullable": "String"}'
[[test]]
name = "string number index concat"
expression = "name[0] + 'x'"
input = '{"name": "hello"}'
[test.loose]
return_type = '"String"'
[test.strict]
diagnostics = [
{ source = "type_check", severity = "error" },
]
[[test]]
name = "string number index coalesce concat"
expression = "(name[0] ?? '') + 'x'"
input = '{"name": "hello"}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '"String"'
[[test]]
name = "flatten nullable array strict error"
expression = "flatten(matrix)"
input = '{"Object": {"matrix": {"Nullable": {"Array": {"Array": "Number"}}}}}'
[test.loose]
return_type = '{"Array": "Number"}'
[test.strict]
return_type = '{"Array": "Number"}'
diagnostics = [{ source = "type_check", severity = "error" }]
[[test]]
name = "flatten nullable array with fallback"
expression = "flatten(matrix ?? [])"
input = '{"Object": {"matrix": {"Nullable": {"Array": {"Array": "Number"}}}}}'
[test.loose]
return_type = '{"Array": "Number"}'
[test.strict]
return_type = '{"Array": "Number"}'
[[test]]
name = "const string number index"
expression = "code[0]"
input = '{"Object": {"code": {"Const": "abc"}}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '{"Nullable": "String"}'
[[test]]
name = "enum string number index"
expression = "status[0]"
input = '{"Object": {"status": {"Enum": [null, ["active", "inactive"]]}}}'
[test.loose]
return_type = '"String"'
[test.strict]
return_type = '{"Nullable": "String"}'