isValidSegmentFilterFromFieldDef = (filter, field) => {
  const {type: filterType, value} = filter;
  const {type: featureType, domain} = field;

  if (featureType === FEATURE_TYPE.CATEGORICAL) {
    assert(domain && domain.length, '`field.domain` must be an array');
    return (
      filterType === FILTER_TYPE.INCLUDE &&
      // filter must contain a subset of column domain
      value.length <= domain.length &&
      value.every(val => domain.includes(val))
    );
  } else if (featureType === FEATURE_TYPE.NUMERICAL) {
    assert(domain && domain.length, '`field.domain` must be an array');
    return (
      filterType === FILTER_TYPE.RANGE &&
      value &&
      value.length === 2 &&
      value[0] < value[1] &&
      // filter must contain a subset of column domain
      (domain[0] >= value[0] || domain[domain.length - 1] <= value[1]) &&
      // filter must be non-empty
      (domain[0] <= value[1] && domain[domain.length - 1] >= value[0])
    );
  } else {
    return filterType === FILTER_TYPE.FUNC && typeof value === 'function';
  }
}
given a filter and the corresponding field definition, determine whether the filter is valid
@param  {Object} filter - contains {name, key, type, value}
@param  {object} field - contains {name, tableFieldIndex, type, dataType, role, domain}
@return {boolean}