RJ
RJ6mo ago

Nested optional search field type error

Given a schema that looks like this:
documents: defineTable({
fieldOne: v.string(),
fieldTwo: v.optional(v.object({
subFieldOne: v.string(),
})),
}).searchIndex("search_field_two", {
searchField: "fieldOne",
filterFields: ["fieldTwo.subFieldOne"],
}),
documents: defineTable({
fieldOne: v.string(),
fieldTwo: v.optional(v.object({
subFieldOne: v.string(),
})),
}).searchIndex("search_field_two", {
searchField: "fieldOne",
filterFields: ["fieldTwo.subFieldOne"],
}),
The following query produces a type error:
const data = await ctx.db
.query("documents")
.withSearchIndex("search_field_two", (q) =>
q
.search("fieldOne", "string")
.eq(
"fieldTwo.subFieldOne",
"string"
// ^ Argument of type '"string"' is not assignable to parameter of type 'undefined'.
)
)
.collect();
const data = await ctx.db
.query("documents")
.withSearchIndex("search_field_two", (q) =>
q
.search("fieldOne", "string")
.eq(
"fieldTwo.subFieldOne",
"string"
// ^ Argument of type '"string"' is not assignable to parameter of type 'undefined'.
)
)
.collect();
Repro: - GH repo: https://github.com/rjdellecese/nested-optional-search-filter-field-test - Offending line: https://github.com/rjdellecese/nested-optional-search-filter-field-test/blob/04dd3545aa0e83ed6deac84b186b6e64e43d4c59/convex/myFunctions.ts#L83
7 Replies
RJ
RJOP6mo ago
Noticing the same thing for vector search
sshader
sshader6mo ago
Thanks for the report -- will look into it (I need a test in https://github.com/get-convex/convex-js/blob/main/src/server/data_model.test.ts + to fiddle with FieldTypeFromFieldPath some more)
GitHub
convex-js/src/server/data_model.test.ts at main · get-convex/convex...
TypeScript/JavaScript client library for Convex. Contribute to get-convex/convex-js development by creating an account on GitHub.
RJ
RJOP6mo ago
Thanks @sshader! If you'd like me to try my hand at a fix, I'd also be willing. I'm not actually sure what the behavior should be here—I assumed it's that nested fields are filterable in both contexts, so they should be T | undefined in the examples above, where T is the type of the nested field?
sshader
sshader6mo ago
Yeah I think desired behavior is T | undefined (at runtime, filtering for both values should work)
Adam Harris
Adam Harris5mo ago
Hi @RJ @sshader I think seeing the same error, but with a standard index. i.e. when I have a schema of the form:
documents: defineTable({
fieldOne: v.string(),
fieldTwo: v.optional(v.object({
subFieldOne: v.string().optional(),
})),
}).index("by_sub_field_one", ["fieldTwo.subFieldOne"]),
documents: defineTable({
fieldOne: v.string(),
fieldTwo: v.optional(v.object({
subFieldOne: v.string().optional(),
})),
}).index("by_sub_field_one", ["fieldTwo.subFieldOne"]),
and I do a query like:
const data = await ctx.db
.query("documents")
.withIndex("by_sub_field_one", (q) =>
q.eq(
"fieldTwo.subFieldOne",
"some string"
// ^ Argument of type '"some string"' is not assignable to parameter of type 'undefined'.
)
)
.collect();
const data = await ctx.db
.query("documents")
.withIndex("by_sub_field_one", (q) =>
q.eq(
"fieldTwo.subFieldOne",
"some string"
// ^ Argument of type '"some string"' is not assignable to parameter of type 'undefined'.
)
)
.collect();
I'm seeing the same error Argument of type '"some string"' is not assignable to parameter of type 'undefined'. Note the extra optional in subFieldOne: v.string().optional(). I expect that this error would still be there if I just had subFieldOne: v.string() but I thought I'd see what the status was before looking into a minimal reproducible example etc... What is the current state of the situation here? Has this been fixed anywhere, or do you have a suggested workaround?
sshader
sshader5mo ago
Not sure if this is the problem here, but the correct syntax is v.optional(v.string()) instead of v.string().optional(). The suggested workaround, as this is just a type error would be to either type cast at "some string" or use a @ts-expect-error comment to silence the type error
Adam Harris
Adam Harris5mo ago
@sshader sorry - I'm actually using zod validators (and copied over here without thinking much) and then using zodToConvex to make the convex validator, so that syntax is correct for a zod validator and it is being transformed to the correct convex validator. But thank you very much for your suggested workarounds! So it this a tracked issue/bug somewhere, so that I can keep an eye on it?