The comparison operators, offered only where DynamoDB can order the
attribute's stored form.
<, <=, >, >= take comparable operands — String, Number and Binary. A
boolean, a Map and a List have no ordering, and DynamoDB rejects a comparison
on one as an incorrect operand type. Absent from the type is better than
either error: the mistake is caught before anything runs. A date keeps its
comparisons through its stored form, as an ISO string that orders
chronologically.
The operands are built per comparable kind, not per member of V. Composed
comparisons may name different values, so an enum's literal union must stay
whole: { $gte: "val-1", $lte: "val-2" } is a range across two members,
which DynamoDB orders as strings. Building one filter per member — what a
conditional distributing over V does — would require every operand to be
the same member. Each kind keeps its own filter, so a union spanning kinds,
as an unresolved dot path's whole scalar union does, never pairs a string
operand with a number one. null and boolean are in no comparable kind,
so they are excluded without an explicit Exclude.
Each kind is drawn out with Extract rather than by testing V against the
whole comparable set. (OrderedFilterValue names the same values; a code
reference rather than a link because that type is internal, so it has no
page on the docs site to point at.) A test against the whole set narrows the
type parameter to V & CheckedType in the true branch — an intersection
TypeScript cannot reduce while V is still generic, as it is in
QueryKeyConditionValue. One narrow type per kind keeps the operands
meaningful there. The difference is invisible at concrete instantiations and
only appears through a generic, so a reviewer who tries the collapse should
test it there.
The comparison operators, offered only where DynamoDB can order the attribute's stored form.
<,<=,>,>=take comparable operands — String, Number and Binary. A boolean, a Map and a List have no ordering, and DynamoDB rejects a comparison on one as an incorrect operand type. Absent from the type is better than either error: the mistake is caught before anything runs. A date keeps its comparisons through its stored form, as an ISO string that orders chronologically.The operands are built per comparable kind, not per member of
V. Composed comparisons may name different values, so an enum's literal union must stay whole:{ $gte: "val-1", $lte: "val-2" }is a range across two members, which DynamoDB orders as strings. Building one filter per member — what a conditional distributing overVdoes — would require every operand to be the same member. Each kind keeps its own filter, so a union spanning kinds, as an unresolved dot path's whole scalar union does, never pairs a string operand with a number one.nullandbooleanare in no comparable kind, so they are excluded without an explicitExclude.Each kind is drawn out with
Extractrather than by testingVagainst the whole comparable set. (OrderedFilterValuenames the same values; a code reference rather than a link because that type is internal, so it has no page on the docs site to point at.) A test against the whole set narrows the type parameter toV & CheckedTypein the true branch — an intersection TypeScript cannot reduce whileVis still generic, as it is inQueryKeyConditionValue. One narrow type per kind keeps the operands meaningful there. The difference is invisible at concrete instantiations and only appears through a generic, so a reviewer who tries the collapse should test it there.