- 
          
 - 
                Notifications
    
You must be signed in to change notification settings  - Fork 282
 
Description
The documentation for the object() schema states:
The
objectschema removes unknown entries. This means that entries that you have not defined in the first argument are not validated and added to the output. You can change this behavior by using thelooseObjectorstrictObjectschema instead.
This can lead to some surprising behavior when all the object's properties are optional. An object schema with all-optional properties will successfully parse any value that is an object, and convert it into an empty object.
The first way this manifests is around arrays. An object schema with all-optional properties will successfully parse an array into an empty object:
const Schema = v.object({
  foo: v.optional(v.string())
});
const result = v.parse(Schema, [1, 2, 3, 4, 5]);
console.log(result);[log]: {}
If we try this with looseObject, it converts the array into a plain object with numeric properties (this is also surprising!):
[log]: {
  0: 1,
  1: 2,
  2: 3,
  3: 4,
  4: 5
}
And strictObject fails as expected.
The second surprising case is around unions, and was brought up in #1317. If an object schema with all-optional properties is put into a union, it'll always succeed, and may strip properties present in other union branches:
let D = v.union([v.object({ a1: v.optional(v.string()) }), v.object({ a2: v.optional(v.string()) })]);
console.log(v.parse(D, { a2: '222' }));[log]: {}
In this case, both looseObject and strictObject will return the correct result: looseObject will not strip a2, and strictObject will make the first union branch fail to parse and move on to the second.
For a future version of Valibot, I think the following API would result in the fewest footguns:
- Remove 
objectentirely. Silently stripping unknown properties just does too many weird things. - Change 
looseObjectso it does not re-create the object. This would make it truly structurally typed, and avoid the surprising array behavior mentioned above. - Keep 
strictObjectas-is. 
I should also mention that it was very surprising to discover that Valibot re-creates every object it parses! All its documentation heavily refers to it as a "validation" library, and I don't expect data to change shape when it is "validated".