#ts schema index error

4 messages · Page 1 of 1 (latest)

lean kraken
#

I have this table definition:
spaceAllocations: defineTable({
bookingId: v.id("bookings"),
bookingItemId: v.union(
v.id("boardingBookingItems"),
v.id("daycareBookingItems"),
),
spaceId: v.id("spaces"),
animalId: v.id("animals"),
start: v.string(), // iso datetime
end: v.string(), // iso datetime
}).index("start_end", ["end", "start"]),


When I write:
export const listSpaceMutationsBetween = query({
args: {
start: v.string(),
end: v.string(),
},
handler: (ctx, { start, end }) => {
ctx.db
.query("spaceAllocations")
.withIndex("start_end", (q) => q.gte("start", start).lte("end", end))
.collect()
},
})


I get a TS error with the above saying: "Argument of type '"start"' is not assignable to parameter of type '"end"'.ts(2345)
"

cinder phoenixBOT
#

Hi @lean kraken. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

The TypeScript error you’re seeing:

Argument of type '"start"' is not assignable to parameter of type '"end"'.ts(2345)

is due to how Convex enforces index field order in queries. When you define an index as:

.index("start_end", ["end", "start"])

the index is ordered first by "end", then by "start". When querying with .withIndex, you must step through the index fields in the order they are defined. This means:

  • The first comparison must be on "end".
  • Only after that can you compare "start".

Your code:

.withIndex("start_end", (q) => q.gte("start", start).lte("end", end))

tries to compare "start" first, which is not allowed. The correct order is to compare "end" first, then "start" if needed. For example:

.withIndex("start_end", (q) => q.gte("end", end).gte("start", start))

But more typically, if you want to query a range between two times, you should use the index fields in the order they are defined. For your index ["end", "start"], a valid query might look like:

.withIndex("start_end", (q) => q.gte("end", end).gte("start", start))

Or, if you want to get all allocations where end is within a range:

.withIndex("start_end", (q) => q.gte("end", start).lte("end", end))

Key point:
You must always compare index fields in the order they are defined in the index. The TypeScript types enforce this to prevent inefficient queries and runtime errors. For more details, see the documentation on querying documents using indexes:

Each equality expression must compare a different index field, starting from the beginning and in order. The upper and lower bounds must follow the equality expressions and compare the next field.