Let's consider a simple serialize function, offering its users the ability to set custom settings to tweak the resulting string

function serialize<T>(instance: T, params: Parameters): string { /* code */ }

In the scenario above, an exhaustive test would have to run throughout all the possible combinations of params with many possible instance. An alternative to such example-based tests would be to rely on properties. It would offer an exhautive coverage of the possible inputs. Given we also have a deserialize function we would simply write:

test('should be able to read itself', () => fc.assert( fc.property( fc.jsonObject(), fc.record({ crlf: fc.boolean(), indent: fc.boolean(), sortKeys: fc.boolean() }, { withDeletedKeys: true }), (instance, params) => { expect(deserialize(serialize(instance, params))).toEqual(instance); } ) ));

Such property was able to detect bugs in both js-yaml and query-string