function createEvent(type, data = {}) {
  const event = document.createEvent('CustomEvent');
  event.initCustomEvent(type, true, true);
  if (data != null) {
    Object.keys(data).forEach(key => {
      const value = data[key];
      if (key === 'timeStamp' && !value) {
        return;
      }
      Object.defineProperty(event, key, {value});
    });
  }
  return event;
}
Native event object mocks for higher-level events.

1. Each event type defines the exact object that it accepts. This ensures
that no arbitrary properties can be assigned to events, and the properties
that don't exist on specific event types (e.g., 'pointerType') are not added
to the respective native event.

2. Properties that cannot be relied on due to inconsistent browser support (e.g., 'x' and 'y') are not
added to the native event. Others that shouldn't be arbitrarily customized (e.g., 'screenX')
are automatically inferred from associated values.

3. PointerEvent and TouchEvent fields are normalized (e.g., 'rotationAngle' -> 'twist')